From 65fc86d2de2570087ed7648d900c30f85dfa164b Mon Sep 17 00:00:00 2001 From: Arijit429 Date: Mon, 13 Apr 2026 19:04:55 +0530 Subject: [PATCH 1/3] test: add edge case coverage for template file routes --- tests/test_template_file_routes.py | 71 ++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests/test_template_file_routes.py diff --git a/tests/test_template_file_routes.py b/tests/test_template_file_routes.py new file mode 100644 index 0000000..7bae8c8 --- /dev/null +++ b/tests/test_template_file_routes.py @@ -0,0 +1,71 @@ +from fastapi.testclient import TestClient +from api.main import app + +client = TestClient(app) + + +def test_upload_template_pdf(): + pdf_content = b"%PDF-1.4 test pdf content" + + files = { + "file": ("sample_test.pdf", pdf_content, "application/pdf") + } + + data = { + "directory": "src/inputs" + } + + response = client.post( + "/templates/upload", + files=files, + data=data + ) + + assert response.status_code == 200 + + response_data = response.json() + + assert "filename" in response_data + assert "pdf_path" in response_data + assert response_data["filename"].endswith(".pdf") + + +def test_preview_template_pdf(): + response = client.get( + "/templates/preview", + params={"path": "src/inputs/file.pdf"} + ) + + assert response.status_code == 200 + assert response.headers["content-type"] == "application/pdf" + +def test_upload_non_pdf_should_fail(): + files = { + "file": ("sample.txt", b"not a pdf", "text/plain") + } + + response = client.post( + "/templates/upload", + files=files, + data={"directory": "src/inputs"} + ) + + assert response.status_code == 400 + + +def test_preview_missing_file_should_fail(): + response = client.get( + "/templates/preview", + params={"path": "src/inputs/does_not_exist.pdf"} + ) + + assert response.status_code == 404 + + +def test_preview_outside_project_should_fail(): + response = client.get( + "/templates/preview", + params={"path": "/etc/passwd"} + ) + + assert response.status_code == 400 From 51521a5680b179d1b444c278c709b9182d09bf71 Mon Sep 17 00:00:00 2001 From: Arijit429 Date: Tue, 14 Apr 2026 00:22:03 +0530 Subject: [PATCH 2/3] feat(frontend): prevent duplicate submit requests --- frontend/app.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/frontend/app.js b/frontend/app.js index 2f6de80..5a3104d 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -32,6 +32,8 @@ const elements = { let templates = loadTemplates(); let activeObjectUrl = null; let selectedTemplateFile = null; +let isTemplateSubmitting = false; +let isFillSubmitting = false; initialize(); @@ -246,6 +248,14 @@ function normalizeFields(rawFields) { async function handleTemplateSubmit(event) { event.preventDefault(); + + if (isTemplateSubmitting) { + setStatus(elements.templateFormMessage, "Request already in progress...", "info"); + return; + } + + isTemplateSubmitting = true; + clearJson(elements.templateFormResponse); setStatus(elements.templateFormMessage, ""); @@ -259,11 +269,13 @@ async function handleTemplateSubmit(event) { "Name, PDF file, and template directory are required.", "error" ); + isTemplateSubmitting = false; return; } if (normalized.error) { setStatus(elements.templateFormMessage, normalized.error, "error"); + isTemplateSubmitting = false; return; } @@ -280,6 +292,7 @@ async function handleTemplateSubmit(event) { }; setStatus(elements.templateFormMessage, "Creating template...", "info"); + const response = await fetch(`${API_BASE_URL}/templates/create`, { method: "POST", headers: { "Content-Type": "application/json" }, @@ -287,12 +300,14 @@ async function handleTemplateSubmit(event) { }); const body = await parseJsonResponse(response); + if (!response.ok) { throw new Error(extractErrorMessage(body, response.status)); } upsertTemplate(body); await refreshTemplatesFromApi(); + elements.fillTemplateId.value = String(body.id || ""); elements.serverPdfPath.value = body.pdf_path || ""; @@ -301,12 +316,16 @@ async function handleTemplateSubmit(event) { `Template created (id: ${body.id}). PDF saved at ${upload.pdf_path}.`, "success" ); + showJson(elements.templateFormResponse, body); } catch (error) { setStatus(elements.templateFormMessage, error.message, "error"); + } finally { + isTemplateSubmitting = false; } } + async function uploadTemplatePdf(file, directory) { const formData = new FormData(); formData.append("file", file, file.name); @@ -327,6 +346,14 @@ async function uploadTemplatePdf(file, directory) { async function handleFillSubmit(event) { event.preventDefault(); + + if (isFillSubmitting) { + setStatus(elements.fillFormMessage, "Request already in progress...", "info"); + return; + } + + isFillSubmitting = true; + clearJson(elements.fillFormResponse); setStatus(elements.fillFormMessage, ""); @@ -335,11 +362,13 @@ async function handleFillSubmit(event) { if (!Number.isInteger(templateId) || templateId < 1) { setStatus(elements.fillFormMessage, "Template ID must be a positive integer.", "error"); + isFillSubmitting = false; return; } if (!inputText) { setStatus(elements.fillFormMessage, "Input text is required.", "error"); + isFillSubmitting = false; return; } @@ -350,6 +379,7 @@ async function handleFillSubmit(event) { try { setStatus(elements.fillFormMessage, "Submitting form fill request...", "info"); + const response = await fetch(`${API_BASE_URL}/forms/fill`, { method: "POST", headers: { "Content-Type": "application/json" }, @@ -357,6 +387,7 @@ async function handleFillSubmit(event) { }); const body = await parseJsonResponse(response); + if (!response.ok) { throw new Error(extractErrorMessage(body, response.status)); } @@ -372,9 +403,12 @@ async function handleFillSubmit(event) { `Form filled (submission id: ${body.id}).`, "success" ); + showJson(elements.fillFormResponse, body); } catch (error) { setStatus(elements.fillFormMessage, error.message, "error"); + } finally { + isFillSubmitting = false; } } From 389b5bf46abb38c8e97a5a12789f6721f9df2b35 Mon Sep 17 00:00:00 2001 From: Arijit429 Date: Tue, 14 Apr 2026 18:46:26 +0530 Subject: [PATCH 3/3] fix(api): add cors middleware for frontend integration --- api/main.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/api/main.py b/api/main.py index 7d81ef6..34e51fb 100644 --- a/api/main.py +++ b/api/main.py @@ -1,26 +1,24 @@ -import os - from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware - from api.routes import forms, templates +from api.db.db import engine +from api.db.models import Template, FormSubmission app = FastAPI() -default_origins = "http://127.0.0.1:5173" -allowed_origins = [ - origin.strip() - for origin in os.getenv("FRONTEND_ORIGINS", default_origins).split(",") - if origin.strip() -] - app.add_middleware( CORSMiddleware, - allow_origins=allowed_origins, - allow_credentials=False, + allow_origins=[ + "http://127.0.0.1:5500", + "http://localhost:5500" + ], + allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) +Template.metadata.create_all(bind=engine) +FormSubmission.metadata.create_all(bind=engine) + app.include_router(templates.router) -app.include_router(forms.router) +app.include_router(forms.router) \ No newline at end of file