Skip to content
Merged
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
3 changes: 0 additions & 3 deletions static/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -915,9 +915,6 @@ if (resetProgressBtn) {
if (!skillsHidden) {
var skillsHidden = document.getElementById("skills");
}
// Keep the hidden <input> in sync for form serialisation
// The API expects a comma-separated string, so join the array that way
skillsHidden.value = selectedSkills.join(", ");
}

updateQuickPickState();
Expand Down
26 changes: 26 additions & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,32 @@ def test_parse_skills_single_entry():
assert parse_skills("JavaScript") == ["javascript"]


def test_parse_skills_valid_json_array():
"""parse_skills should parse a valid JSON array of skills."""
result = parse_skills('["Python","React"]')
assert result == ["python", "react"]


def test_parse_skills_malformed_json_handling():
"""parse_skills should handle malformed JSON gracefully using fallback."""
# Should not crash, and parses via fallback comma-splitting behavior
result = parse_skills('["Python",]')
assert isinstance(result, list)
assert len(result) > 0


def test_parse_skills_legacy_fallback():
"""parse_skills should parse a legacy comma-separated string."""
result = parse_skills("Python,React")
assert result == ["python", "react"]


def test_parse_skills_containing_commas():
"""parse_skills should preserve skill names containing commas when using JSON."""
result = parse_skills('["HTML, CSS","JavaScript"]')
assert result == ["html, css", "javascript"]


def test_score_single_project_full_match():
"""A project that matches all four criteria should receive the maximum score."""
project = {
Expand Down
36 changes: 26 additions & 10 deletions utils/recommender.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,34 @@

def parse_skills(skills_string):
"""
Convert a raw comma-separated skills string into
a normalized lowercase list.
Convert a skills string into a normalized lowercase list.

Example:
"JS, HTML5, CSS3" -> ["javascript", "html", "css"]
"""
Accepts two formats:
1. JSON array (preferred): '["HTML, CSS", "JavaScript"]'
Handles skill names that contain commas without mis-splitting.
2. Comma-separated string (legacy fallback): "HTML, CSS, JavaScript"

raw_skills = [
s.strip().lower()
for s in skills_string.split(",")
if s.strip()
]
Example:
'["JS", "HTML5", "CSS3"]' -> ["javascript", "html", "css"]
"""
import json

# Skills are serialized as JSON arrays.
# Legacy comma-separated values remain supported for compatibility.
try:
# Preferred path: frontend sends a JSON-serialized array
parsed = json.loads(skills_string)
if isinstance(parsed, list):
raw_skills = [s.strip().lower() for s in parsed if isinstance(s, str) and s.strip()]
else:
raise ValueError("Parsed JSON is not a list")
except (json.JSONDecodeError, ValueError, TypeError):
# Fallback: handle plain comma-separated strings
raw_skills = [
s.strip().lower()
for s in skills_string.split(",")
if s.strip()
]

normalized_skills = []
for skill in raw_skills:
Expand Down
Loading