"""Unit tests for FormData.from_sheet_row + sheet row helpers. No DB, no network. Pins the Google Form Responses header keys and YoG rules. """ from __future__ import annotations from datetime import datetime, timezone from g_sheet import plugins from g_sheet.enums import FORM_DATA_FIELDS from g_sheet.models import FormData FORM_RESPONSE_RECORD = { "Timestamp": "7/2/2026 17:50:19", "Email": "nusratazra@gmail.com", "Full Name": "Nusrat Azra", "Gender": "Female", "Date of Birth": "7/24/1984", "Marital Status": "Single", "CGPA": "3.5", "University": "Karachi University", "If your university is not listed above, please specify its name.": "", "Educational Degree": "Masters", "Year of Graduation": "12/2/2007", "Position Applied For": "Executive Secretary", "LinkedIn Profile Link": ( "https://www.linkedin.com/in/nusrat-azra-executive-manager-to-c-suite-3bb86719/" ), "Drop your updated resume": "https://drive.google.com/open?id=1l5HOY5R6KiL6270A_sV56FkdX6EIGfI4", "How soon can you join us?": "1 - 2 weeks", "Phone number (03XX-XXXXXXX)": "03312464228", "Are you willing to relocate?": "Yes", "Residing City": "Karachi", "Residing Country": "Pakistan", "Area of Interest": "", "Recruiter": "", "Director / POC / Category": "Operations", "National Identification No. (42000-XXXXXXX-X)": "4250105627772", "Where did you hear about the position you're applying for?": "Indeed", "Current Salary": "110k", "Expected Salary": "150k", "HR Comment": "Good profile", } def test_from_sheet_row_maps_form_response_keys(): mapped = FormData.from_sheet_row( "Form Responses - Candidate Database Sheet 2026", 9, FORM_RESPONSE_RECORD, ) assert mapped["name"] == "Nusrat Azra" assert mapped["candidate_email"] == "nusratazra@gmail.com" assert mapped["candidate_number"] == "03312464228" assert mapped["gender"] == "Female" assert mapped["date_of_birth"] == datetime(1984, 7, 24, tzinfo=timezone.utc) assert mapped["cnic"] == "4250105627772" assert mapped["cgpa"] == "3.5" assert mapped["degree"] == "Masters" assert mapped["university"] == "Karachi University" assert mapped["position_applied_for"] == "Executive Secretary" assert mapped["notice_period"] == "1 - 2 weeks" assert mapped["source_of_application"] == "Indeed" assert mapped["ho_availability"] == "Yes" assert mapped["marital_status"] == "Single" assert mapped["residing_city"] == "Karachi" assert mapped["city"] == "Karachi" assert mapped["residing_country"] == "Pakistan" assert mapped["director_poc_category"] == "Operations" assert mapped["hr_comments"] == "Good profile" assert mapped["current_salary_value"] == 110000 assert mapped["expected_salary_value"] == 150000 assert mapped["entry_year"] == "12/2/2007" assert mapped["entry_date"] is not None assert mapped["entry_time"] == "17:50" assert mapped["name"] != "7/2/2026 17:50:19" assert mapped["row_number"] == 9 assert mapped["sheet"] == "Form Responses - Candidate Database Sheet 2026" assert mapped["raw_record"]["Full Name"] == "Nusrat Azra" def test_year_of_graduation_prefers_second_when_present(): data = { "Full Name": "Ada", "Year of Graduation": "2010", "Year of Graduation_1": "2015", } mapped = FormData.from_sheet_row("tab", 2, data) assert mapped["entry_year"] == "2015" def test_year_of_graduation_uses_first_when_second_blank(): data = { "Full Name": "Ada", "Year of Graduation": "2010", "Year of Graduation_1": " ", } mapped = FormData.from_sheet_row("tab", 2, data) assert mapped["entry_year"] == "2010" def test_year_of_graduation_none_when_both_blank(): data = { "Full Name": "Ada", "Year of Graduation": "", "Year of Graduation_1": "", } mapped = FormData.from_sheet_row("tab", 2, data) assert mapped["entry_year"] is None def test_year_of_graduation_single_column(): data = {"Full Name": "Ada", "Year of Graduation": "2012"} mapped = FormData.from_sheet_row("tab", 2, data) assert mapped["entry_year"] == "2012" def test_from_sheet_row_canonicalizes_city_keeps_raw_residing(): data = {**FORM_RESPONSE_RECORD, "Residing City": "Karachi(Malir)"} mapped = FormData.from_sheet_row("tab", 9, data) assert mapped["city"] == "Karachi" assert mapped["residing_city"] == "Karachi(Malir)" def test_duplicate_year_header_becomes_year_of_graduation_1(): headers = plugins.normalise_headers( ["Full Name", "Year of Graduation", "Year of Graduation"], ) assert headers == ["Full Name", "Year of Graduation", "Year of Graduation_1"] def test_parse_salary_and_score(): assert plugins.parse_salary("110k") == 110000 assert plugins.parse_salary("60k-70k") == 60000 assert plugins.parse_salary("Negotiable") is None assert plugins.parse_score("7") == 7 assert plugins.parse_score("15") is None def test_rows_to_indexed_records_keeps_true_sheet_row_across_blank(): rows = [ ["Name", "Age"], ["Ada", "30"], ["", ""], ["Bob", "40"], ] indexed = plugins.rows_to_indexed_records(rows) assert indexed == [ (2, {"Name": "Ada", "Age": "30"}), (4, {"Name": "Bob", "Age": "40"}), ] assert plugins.rows_to_records(rows) == [ {"Name": "Ada", "Age": "30"}, {"Name": "Bob", "Age": "40"}, ] def test_form_data_fields_match_model(): assert set(FORM_DATA_FIELDS) == set(FormData.model_fields) def test_drive_file_id_from_form_open_url(): url = "https://drive.google.com/open?id=1l5HOY5R6KiL6270A_sV56FkdX6EIGfI4" assert plugins.drive_file_id(url) == "1l5HOY5R6KiL6270A_sV56FkdX6EIGfI4" def test_drive_file_id_from_file_view_url(): url = "https://drive.google.com/file/d/abc123XYZ/view?usp=sharing" assert plugins.drive_file_id(url) == "abc123XYZ" def test_drive_file_id_from_docs_url(): url = "https://docs.google.com/document/d/docFileId99/edit" assert plugins.drive_file_id(url) == "docFileId99" def test_drive_file_id_rejects_folder_and_non_drive(): assert plugins.drive_file_id("https://drive.google.com/drive/folders/abc") is None assert plugins.drive_file_id("https://example.com/cv.pdf") is None assert plugins.drive_file_id("") is None assert plugins.drive_file_id(None) is None def test_cv_dest_path_stays_inside_dir(tmp_path): dest = plugins._cv_dest_path(tmp_path, "1l5HOY5R6KiL6270A_sV56FkdX6EIGfI4", "Resume.PDF") assert dest.parent == tmp_path.resolve() assert dest.name.endswith(".pdf") assert dest.name.startswith("1l5HOY5R6KiL6270A_sV56FkdX6EIGfI4") def test_title_ilike_pattern_contains_and_escapes(): from job.job_post.models import JobPosts assert JobPosts.title_ilike_pattern("") is None assert JobPosts.title_ilike_pattern(" ") is None assert JobPosts.title_ilike_pattern("Brand Manager") == "%Brand Manager%" assert JobPosts.title_ilike_pattern("C++ _dev%") == r"%C++ \_dev\%%" async def test_stamp_suggested_job_posts_sets_ids_or_empty(monkeypatch): import uuid job_a = uuid.uuid4() job_b = uuid.uuid4() async def fake_ids(session, titles): return {"Executive Secretary": [job_a, job_b]} monkeypatch.setattr( "job.job_post.models.JobPosts.ids_for_titles_ilike", fake_ids, ) records = [ {"position_applied_for": "Executive Secretary"}, {"position_applied_for": "Unknown Role"}, {"position_applied_for": None}, {"position_applied_for": " "}, ] out = await FormData.stamp_suggested_job_posts(object(), records) assert out[0]["suggested_job_post_ids"] == [str(job_a), str(job_b)] assert out[0]["job_post_id"] is None assert out[0]["assigned_job_post_id"] is None assert out[1]["suggested_job_post_ids"] == [] assert out[1]["job_post_id"] is None assert out[1]["assigned_job_post_id"] is None assert out[2]["suggested_job_post_ids"] == [] assert out[3]["suggested_job_post_ids"] == [] def test_score_job_ids_assigned_wins_else_suggested(): import uuid a = uuid.uuid4() b = uuid.uuid4() assigned = uuid.uuid4() assert FormData.score_job_ids({ "suggested_job_post_ids": [str(a), str(b)], "assigned_job_post_id": assigned, }) == [assigned] assert FormData.score_job_ids({ "suggested_job_post_ids": [str(a), str(b)], "job_post_id": assigned, }) == [assigned] assert FormData.score_job_ids({ "suggested_job_post_ids": [str(a), str(b), str(a)], "assigned_job_post_id": None, "job_post_id": None, }) == [a, b] assert FormData.score_job_ids({"suggested_job_post_ids": None}) == [] assert FormData.score_job_ids(None) == []