From 62ad4e92689b34701a22d2bebdd9d7fe26d6aae5 Mon Sep 17 00:00:00 2001 From: Syed Faisal Haque Date: Sun, 17 May 2026 22:48:56 +0530 Subject: [PATCH 1/2] fix: return all validation errors from /api/recommend Previously only errors[0] was returned, forcing users to fix and resubmit one field at a time. The response key is now "errors" (list). Also moves `import os` to module level in download_code(). --- CHANGELOG.md | 2 +- routes/main_routes.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2d09e56..d293d57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,4 +17,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed -- No fixes recorded yet \ No newline at end of file +- `/api/recommend` now returns all validation errors in a single response instead of only the first one, so users can correct every invalid field at once \ No newline at end of file diff --git a/routes/main_routes.py b/routes/main_routes.py index 4cce0460..fd12b1cd 100644 --- a/routes/main_routes.py +++ b/routes/main_routes.py @@ -3,6 +3,8 @@ # Each route is kept thin: it validates input, calls a utility function, # and returns a response. No business logic lives here. +import os + from flask import Blueprint, render_template, request, jsonify, send_from_directory, abort from utils.recommender import get_recommendations, validate_recommendation_inputs @@ -44,8 +46,7 @@ def recommend(): # Validate before running the recommendation engine errors = validate_recommendation_inputs(skills, level, interest, time_availability) if errors: - # Return only the first error to keep the UI message clean - return jsonify({"error": errors[0]}), 400 + return jsonify({"errors": errors}), 400 results = get_recommendations(skills, level, interest, time_availability) @@ -95,6 +96,5 @@ def download_code(project_id): if not full_path: abort(404) - import os filename = os.path.basename(full_path) return send_from_directory(get_starter_code_dir(), filename, as_attachment=True) From cd30f01f61d7843c24f600bd38d5156a7c0ac7b7 Mon Sep 17 00:00:00 2001 From: Syed Faisal Haque Date: Tue, 19 May 2026 23:23:40 +0530 Subject: [PATCH 2/2] fix: update test and frontend to use new errors response key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_recommend_api_missing_field was asserting the old "error" string key — updated to assert "errors" list key and verify it is non-empty. static/script.js was reading data.error (string) from /api/recommend — updated to read data.errors (list) and join all messages for display so the user sees every validation problem at once. --- static/script.js | 5 +++-- tests/test_basic.py | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/static/script.js b/static/script.js index aebc9225..abb76d8a 100644 --- a/static/script.js +++ b/static/script.js @@ -437,9 +437,10 @@ if (isIndexPage) { .then(function (res) { return res.json(); }) .then(function (data) { setLoadingState(false); - if (data.error) { + if (data.errors && data.errors.length) { + // Show all validation errors joined so the user can fix every field at once var generalErr = document.getElementById("form-error-general"); - if (generalErr) generalErr.textContent = data.error; + if (generalErr) generalErr.textContent = data.errors.join(" | "); return; } renderResults(data.projects || [], data.message); diff --git a/tests/test_basic.py b/tests/test_basic.py index 6bef8abc..cdfc7517 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -231,7 +231,10 @@ def test_recommend_api_missing_field(): "time": "Low" }) assert response.status_code in (400, 415) - assert "error" in response.get_json() + data = response.get_json() + assert "errors" in data + assert isinstance(data["errors"], list) + assert len(data["errors"]) > 0 def test_recommend_api_empty_body():