105 lines
4.5 KiB
Python
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()
|
|
|