adobe-to-docusign-migrator/src/test_mapping.py

105 lines
4.5 KiB
Python

# 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()