# Mapping Function Unit Test """ Unit test harness for mapping Adobe Sign form fields to DocuSign tab config. Validates that compose_docusign_template.py produces correctly structured output: - Tabs are grouped into typed arrays (textTabs, signHereTabs, etc.) - required / locked are strings "true" / "false", not booleans - listTabs have listItems: [{text, value}], not a string array - radioGroupTabs have groupName + radios[] - No top-level "status" field - No email/name on signer role placeholders """ import json import sys from pathlib import Path from pprint import pprint # Support running from src/ or project root BASE = Path(__file__).parent.parent sys.path.insert(0, str(Path(__file__).parent)) from compose_docusign_template import compose_template def test_onboarding_mapping(): output_path = BASE / "validation" / "compose-doc-template-complete.json" compose_template( fields_path=str(BASE / "sample-templates" / "onboarding-template-formfields.json"), template_meta_path=str(BASE / "sample-templates" / "onboarding-template.json"), pdf_b64_path=str(BASE / "sample-templates" / "onboarding-sample.pdf.b64"), output_path=str(output_path), ) template = json.loads(output_path.read_text()) # -- No top-level status field -- assert "status" not in template, "Template must not have a top-level 'status' field" signers = template["recipients"]["signers"] assert len(signers) == 2, f"Expected 2 signers, got {len(signers)}" signer0_tabs = signers[0]["tabs"] signer1_tabs = signers[1]["tabs"] # -- No email/name on role placeholders -- for s in signers: assert "email" not in s, f"Signer should not have 'email' in template role: {s['roleName']}" assert "name" not in s, f"Signer should not have 'name' in template role: {s['roleName']}" # -- Tab groups present and properly typed -- assert "textTabs" in signer0_tabs, "Signer 0 missing textTabs" assert "dateSignedTabs" in signer0_tabs, "Signer 0 missing dateSignedTabs" assert "listTabs" in signer0_tabs, "Signer 0 missing listTabs" assert "checkboxTabs" in signer0_tabs, "Signer 0 missing checkboxTabs" assert "radioGroupTabs" in signer0_tabs, "Signer 0 missing radioGroupTabs" assert "signHereTabs" in signer0_tabs, "Signer 0 missing signHereTabs" assert "textTabs" in signer1_tabs, "Signer 1 missing textTabs" assert "signHereTabs" in signer1_tabs, "Signer 1 missing signHereTabs" # -- required / locked are strings -- for tab in signer0_tabs.get("textTabs", []): assert isinstance(tab.get("required"), str), f"required must be string, got {type(tab.get('required'))}" for tab in signer0_tabs.get("listTabs", []): assert isinstance(tab.get("required"), str), f"required must be string on listTab" # -- listItems are objects -- list_tab = signer0_tabs["listTabs"][0] assert "listItems" in list_tab, "listTab missing listItems" assert isinstance(list_tab["listItems"][0], dict), "listItems entries must be {text, value} dicts" assert "text" in list_tab["listItems"][0], "listItems entries must have 'text'" assert "value" in list_tab["listItems"][0], "listItems entries must have 'value'" # -- radioGroupTabs structure -- radio_tab = signer0_tabs["radioGroupTabs"][0] assert "groupName" in radio_tab, "radioGroupTab missing groupName" assert "radios" in radio_tab, "radioGroupTab missing radios" assert len(radio_tab["radios"]) == 3, f"Expected 3 radios, got {len(radio_tab['radios'])}" for r in radio_tab["radios"]: assert "pageNumber" in r, "radio missing pageNumber" assert "xPosition" in r, "radio missing xPosition" assert "yPosition" in r, "radio missing yPosition" assert "value" in r, "radio missing value" # -- All tabs have required placement fields -- all_single_tabs = ( signer0_tabs.get("textTabs", []) + signer0_tabs.get("dateSignedTabs", []) + signer0_tabs.get("signHereTabs", []) + signer0_tabs.get("listTabs", []) + signer0_tabs.get("checkboxTabs", []) + signer1_tabs.get("textTabs", []) + signer1_tabs.get("signHereTabs", []) ) for tab in all_single_tabs: for field in ("documentId", "pageNumber", "xPosition", "yPosition"): assert field in tab, f"Tab '{tab.get('tabLabel')}' missing '{field}'" print("✅ All mapping assertions passed!") print("\n--- Generated template (recipients section) ---") pprint(template["recipients"]) if __name__ == "__main__": test_onboarding_mapping()