Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,4 @@ app.*.symbols
venv/
.venv/

.DS_Store
46 changes: 46 additions & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,38 @@ def test_validate_all_valid():
errors = validate_recommendation_inputs("Python", "Beginner", "Web", "Low")
assert errors == [], f"Unexpected errors: {errors}"

def test_validate_invalid_level():
"""Invalid level should return an error."""
errors = validate_recommendation_inputs(
"Python",
"Expert",
"Web",
"Low"
)
assert any("Invalid experience level" in e for e in errors)


def test_validate_invalid_interest():
"""Invalid interest should return an error."""
errors = validate_recommendation_inputs(
"Python",
"Beginner",
"Blockchain",
"Low"
)
assert any("Invalid interest" in e for e in errors)


def test_validate_invalid_time():
"""Invalid time should return an error."""
errors = validate_recommendation_inputs(
"Python",
"Beginner",
"Web",
"Very High"
)
assert any("Invalid time availability" in e for e in errors)


def test_validate_missing_skills():
"""An empty skills field must produce an error."""
Expand Down Expand Up @@ -284,6 +316,20 @@ def test_recommend_api_missing_field():
assert response.status_code in (400, 415)
assert "error" in response.get_json()

def test_recommend_api_invalid_level():
"""API should return 400 for invalid experience level."""
client = get_client()

response = client.post("/api/recommend", json={
"skills": "Python",
"level": "Expert",
"interest": "Data",
"time": "Low"
})

assert response.status_code == 400
assert "error" in response.get_json()


def test_recommend_api_empty_body():
"""The API should return 400 when the body is not valid JSON."""
Expand Down
42 changes: 41 additions & 1 deletion utils/recommender.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,31 @@
"c++": "cpp",
"web dev": "javascript"
}
VALID_LEVELS = {
"beginner",
"intermediate",
"advanced"
}

VALID_TIME = {
"low",
"medium",
"high"
}

VALID_INTERESTS = {
"web",
"data",
"education",
"automation",
"games",
"machine learning/ai",
"devops",
"mobile",
"artificial intelligence",
"cloud computing",
"mobile app development",
}


def parse_skills(skills_string):
Expand Down Expand Up @@ -133,7 +158,7 @@ def get_recommendations(skills_string, level, interest, time_availability):

def validate_recommendation_inputs(skills, level, interest, time_availability):
"""
Validate all four required fields.
Validate all recommendation inputs.
Returns a list of error strings. An empty list means all inputs are valid.
"""
errors = []
Expand All @@ -143,11 +168,26 @@ def validate_recommendation_inputs(skills, level, interest, time_availability):

if not level or not level.strip():
errors.append("Please select an experience level.")
elif level.strip().lower() not in VALID_LEVELS:
errors.append(
"Invalid experience level. "
"Choose Beginner, Intermediate, or Advanced."
)

if not interest or not interest.strip():
errors.append("Please select an area of interest.")
elif interest.strip().lower() not in VALID_INTERESTS:
errors.append(
"Invalid interest. "
"Choose a supported interest area."
)

if not time_availability or not time_availability.strip():
errors.append("Please select your time availability.")
elif time_availability.strip().lower() not in VALID_TIME:
errors.append(
"Invalid time availability. "
"Choose Low, Medium, or High."
)

return errors
Loading