diff --git a/src/utils/recommender.py b/src/utils/recommender.py index c481bd30..369790ab 100644 --- a/src/utils/recommender.py +++ b/src/utils/recommender.py @@ -662,6 +662,8 @@ def get_recommendations( for entry in skill_entries } all_projects = load_all_projects() + if tech_stack and tech_stack.lower() != "all": + all_projects = [p for p in all_projects if project_matches_tech(p, tech_stack)] # Load NLP model to determine if we should use semantic search model = get_nlp_model() diff --git a/tests/test_recommender_tech_stack.py b/tests/test_recommender_tech_stack.py new file mode 100644 index 00000000..70559837 --- /dev/null +++ b/tests/test_recommender_tech_stack.py @@ -0,0 +1,44 @@ +# tests/test_recommender_tech_stack.py +# Regression test for issue #1870: +# The technology stack filter must actually narrow the recommendations returned +# by get_recommendations (project_matches_tech was defined but never called). + +from utils.recommender import get_recommendations, project_matches_tech + + +def test_all_returns_everything(): + """With tech_stack='all' the filter must not exclude any project.""" + results = get_recommendations("Python", "Beginner", "Data", "Low", tech_stack="all") + assert len(results["recommendations"]) > 0 + + +def test_tech_stack_filter_changes_results(): + """A non-'all' tech stack must produce a different recommendation set.""" + base = get_recommendations("Python", "Beginner", "Data", "Low", tech_stack="all") + filtered = get_recommendations("Python", "Beginner", "Data", "Low", tech_stack="java") + base_ids = [p["id"] for p in base["recommendations"]] + filtered_ids = [p["id"] for p in filtered["recommendations"]] + assert filtered_ids != base_ids, ( + "tech_stack filter had no effect (issue #1870)" + ) + + +def test_filtered_projects_actually_match_tech(): + """Every project returned for a given tech_stack must match it.""" + filtered = get_recommendations("Python", "Beginner", "Data", "Low", tech_stack="java") + assert filtered["recommendations"], "Expected at least one java project to match" + for project in filtered["recommendations"]: + assert project_matches_tech(project, "java"), ( + f"Project {project.get('id')} does not match tech_stack='java' (issue #1870)" + ) + + +def test_filtered_results_are_subset_of_all(): + """Filtered results must never include projects the 'all' query excludes.""" + base = get_recommendations("Python", "Beginner", "Data", "Low", tech_stack="all") + filtered = get_recommendations("Python", "Beginner", "Data", "Low", tech_stack="flask") + base_ids = {p["id"] for p in base["recommendations"]} + for project in filtered["recommendations"]: + assert project["id"] in base_ids, ( + f"Project {project.get('id')} returned by filter but absent from unfiltered query" + )