@salesforce/afv-skills 1.54.0 → 1.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-generate/SKILL.md +8 -0
  3. package/skills/agentforce-generate/references/actions-reference.md +2 -2
  4. package/skills/agentforce-generate/references/voice-modality-reference.md +51 -15
  5. package/skills/agentforce-generate/references/voice-telephony-cli.md +193 -0
  6. package/skills/agentforce-observe/SKILL.md +13 -9
  7. package/skills/agentforce-observe/references/ahm-alerts.md +193 -14
  8. package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +24 -15
  9. package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +11 -0
  10. package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +33 -1
  11. package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +32 -1
  12. package/skills/automation-sandbox-post-copy-configure/SKILL.md +75 -71
  13. package/skills/automation-sandbox-post-copy-configure/assets/scheduled_apex_template.apex +13 -0
  14. package/skills/automation-sandbox-post-copy-configure/examples/sample_scheduled_apex_config.json +13 -0
  15. package/skills/automation-sandbox-post-copy-configure/references/scheduled_apex_path.md +155 -0
  16. package/skills/automation-sandbox-post-copy-configure/scripts/build-scheduled-apex.mjs +62 -0
  17. package/skills/automation-sandbox-post-copy-configure/scripts/soql-escape-job-name.mjs +28 -0
  18. package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +383 -0
  19. package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +324 -0
  20. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +63 -0
  21. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +100 -0
  22. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -0
  23. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +46 -0
  24. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/04-deploy-engine.js +198 -0
  25. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/05-deploy-tpm-accruals.js +231 -0
  26. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +82 -0
  27. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +517 -0
  28. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +416 -0
  29. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -0
  30. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +514 -0
  31. package/skills/consumer-goods-sync-management-configure/SKILL.md +137 -0
  32. package/skills/consumer-goods-sync-management-configure/examples/scenarios.md +294 -0
  33. package/skills/consumer-goods-sync-management-configure/references/act1-setup-sync.md +333 -0
  34. package/skills/consumer-goods-sync-management-configure/references/act2-assign-users.md +324 -0
  35. package/skills/consumer-goods-sync-management-configure/references/act3-plan-verify.md +113 -0
  36. package/skills/consumer-goods-sync-management-configure/references/readiness-and-enablement.md +164 -0
  37. package/skills/consumer-goods-sync-management-configure/references/sync-management-app-install-backbone.md +159 -0
  38. package/skills/consumer-goods-sync-management-configure/references/transports-and-namespace.md +220 -0
  39. package/skills/consumer-goods-sync-management-configure/references/verify-and-smoke.md +175 -0
  40. package/skills/dx-org-analyze/README.md +310 -0
  41. package/skills/dx-org-analyze/SKILL.md +260 -0
  42. package/skills/dx-org-analyze/references/collection-details.md +88 -0
  43. package/skills/dx-org-analyze/references/report-format.md +67 -0
  44. package/skills/dx-org-analyze/scripts/collect_org_data.py +823 -0
  45. package/skills/dx-org-analyze/scripts/compute_diff.py +1101 -0
  46. package/skills/dx-org-analyze/scripts/introspect_org.py +400 -0
  47. package/skills/dx-org-analyze/tests/README.md +46 -0
  48. package/skills/dx-org-analyze/tests/fixtures/org_a.json +76 -0
  49. package/skills/dx-org-analyze/tests/fixtures/org_b.json +70 -0
  50. package/skills/dx-org-analyze/tests/test_compute_diff.sh +284 -0
  51. package/skills/dx-org-analyze/tests/test_consistency.sh +428 -0
  52. package/skills/dx-org-manage/SKILL.md +6 -50
  53. package/skills/dx-org-manage/examples/README.md +10 -16
  54. package/skills/dx-org-manage/references/scratch-org-create.md +1 -1
  55. package/skills/dx-org-manage/references/scratch-org-operations.md +1 -1
  56. package/skills/dx-org-shape-manage/SKILL.md +4 -3
  57. package/skills/education-cloud-domain-configure/references/gotchas-extended.md +1 -0
  58. package/skills/experience-accessibility-validate/SKILL.md +8 -5
  59. package/skills/experience-accessibility-validate/references/reviewers/sc-1-1-1-non-text-content.md +1 -4
  60. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-i-lists.md +0 -4
  61. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-ii-tables.md +20 -85
  62. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-iii-form-labels.md +4 -4
  63. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-iv-regions.md +0 -4
  64. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-v-groups.md +2 -4
  65. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-5-identify-input.md +0 -4
  66. package/skills/experience-accessibility-validate/references/reviewers/sc-1-4-3-contrast.md +4 -14
  67. package/skills/experience-accessibility-validate/references/reviewers/sc-2-1-1-keyboard.md +9 -5
  68. package/skills/experience-accessibility-validate/references/reviewers/sc-2-4-4-link-purpose.md +1 -4
  69. package/skills/experience-accessibility-validate/references/reviewers/sc-2-4-6-headings-labels.md +0 -4
  70. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-1-pointer-gestures.md +0 -4
  71. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-2-pointer-cancellation.md +0 -4
  72. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-3-label-in-name.md +0 -4
  73. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-7-dragging-movement.md +0 -4
  74. package/skills/experience-accessibility-validate/references/reviewers/sc-3-2-1-on-focus.md +0 -4
  75. package/skills/experience-accessibility-validate/references/reviewers/sc-3-2-2-on-input.md +1 -4
  76. package/skills/experience-accessibility-validate/references/reviewers/sc-3-3-1-error-identification.md +1 -4
  77. package/skills/experience-accessibility-validate/references/reviewers/sc-3-3-2-labels-instructions.md +1 -4
  78. package/skills/experience-accessibility-validate/references/reviewers/sc-3-3-3-error-suggestion.md +1 -4
  79. package/skills/experience-accessibility-validate/references/reviewers/sc-4-1-2-i-name.md +4 -5
  80. package/skills/experience-accessibility-validate/references/reviewers/sc-4-1-2-ii-role.md +1 -4
  81. package/skills/experience-accessibility-validate/references/reviewers/sc-4-1-2-iii-value.md +0 -4
  82. package/skills/experience-design-validate/SKILL.md +163 -0
  83. package/skills/experience-design-validate/references/ai.md +54 -0
  84. package/skills/experience-design-validate/references/components.md +61 -0
  85. package/skills/experience-design-validate/references/craft.md +158 -0
  86. package/skills/experience-design-validate/references/data.md +59 -0
  87. package/skills/experience-design-validate/references/forms-flows.md +57 -0
  88. package/skills/experience-design-validate/references/interaction.md +53 -0
  89. package/skills/experience-design-validate/references/navigation.md +51 -0
  90. package/skills/experience-design-validate/references/performance.md +56 -0
  91. package/skills/experience-design-validate/references/records.md +60 -0
  92. package/skills/experience-design-validate/references/responsive.md +48 -0
  93. package/skills/experience-design-validate/references/scoring-rubric.md +257 -0
  94. package/skills/experience-design-validate/references/state.md +53 -0
  95. package/skills/experience-design-validate/references/trust.md +47 -0
  96. package/skills/experience-design-validate/references/usability.md +35 -0
  97. package/skills/experience-design-validate/references/visual-system.md +183 -0
  98. package/skills/experience-lwc-accessibility-jest-run/SKILL.md +104 -25
  99. package/skills/experience-lwc-accessibility-jest-run/assets/jest.config.js +4 -0
  100. package/skills/experience-lwc-accessibility-jest-run/assets/sa11y-jest-setup.js +5 -0
  101. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +5 -5
  102. package/skills/experience-ui-bundle-features-generate/SKILL.md +65 -36
  103. package/skills/experience-ui-bundle-features-generate/references/angular/features.md +74 -0
  104. package/skills/experience-ui-bundle-features-generate/references/react/features.md +59 -0
  105. package/skills/experience-ui-bundle-features-generate/scripts/detect-framework.sh +73 -0
  106. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +2 -2
  107. package/skills/experience-ui-bundle-metadata-generate/SKILL.md +26 -14
  108. package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +37 -0
  109. package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +32 -0
  110. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +73 -0
  111. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +30 -8
  112. package/skills/field-service-data-capture-migrate/SKILL.md +391 -0
  113. package/skills/field-service-data-capture-migrate/assets/sample-legacy-flow.flow-meta.xml +163 -0
  114. package/skills/field-service-data-capture-migrate/references/architecture-notes.md +40 -0
  115. package/skills/field-service-data-capture-migrate/references/component-mapping.md +278 -0
  116. package/skills/field-service-data-capture-migrate/references/converter-builder-contract.md +183 -0
  117. package/skills/field-service-data-capture-migrate/references/dc-platform-rules.md +130 -0
  118. package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +215 -0
  119. package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +36 -0
  120. package/skills/field-service-data-capture-migrate/references/migration-checklist.md +121 -0
  121. package/skills/field-service-data-capture-migrate/references/transformer-rules.md +132 -0
  122. package/skills/field-service-data-capture-migrate/scripts/analyze_flow.py +277 -0
  123. package/skills/field-service-data-capture-migrate/scripts/convert_to_dc_spec.py +1311 -0
  124. package/skills/field-service-data-capture-migrate/scripts/cud_analysis.py +402 -0
  125. package/skills/field-service-data-capture-migrate/scripts/deploy_flow.sh +230 -0
  126. package/skills/field-service-data-capture-migrate/scripts/discover_subflow_tree.py +230 -0
  127. package/skills/field-service-data-capture-migrate/scripts/flow_input.py +186 -0
  128. package/skills/field-service-data-capture-migrate/scripts/flow_xml_utils.py +39 -0
  129. package/skills/field-service-data-capture-migrate/scripts/fsm_dc_catalog.py +413 -0
  130. package/skills/field-service-data-capture-migrate/scripts/generate_summary.py +199 -0
  131. package/skills/field-service-data-capture-migrate/scripts/json_to_flow_xml.py +146 -0
  132. package/skills/field-service-data-capture-migrate/scripts/manual_review_flags.py +42 -0
  133. package/skills/field-service-data-capture-migrate/scripts/retrieve_flow_rest.sh +155 -0
  134. package/skills/field-service-data-capture-migrate/scripts/subflow_names.py +49 -0
  135. package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +1661 -0
  136. package/skills/field-service-data-capture-migrate/scripts/validate_flow.sh +147 -0
  137. package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +1258 -0
  138. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +1 -1
  139. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +1 -1
  140. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +14 -1
  141. package/skills/mobile-apps-create/SKILL.md +1 -1
  142. package/skills/{platform-agentsetup-categories-fetch → platform-agenticsetup-categories-get}/SKILL.md +7 -7
  143. package/skills/platform-sandbox-configure/SKILL.md +108 -133
  144. package/skills/platform-sandbox-configure/references/api-response-shapes.md +39 -0
  145. package/skills/platform-sandbox-configure/references/definition-file-approach.md +73 -0
  146. package/skills/platform-widget-generate/SKILL.md +26 -18
  147. package/skills/platform-widget-generate/examples/formulas.json +191 -0
  148. package/skills/platform-widget-generate/references/widget-formulas.md +123 -0
  149. package/skills/platform-widget-generate/references/widget-meta-directives.md +4 -4
  150. package/skills/sales-call-scoring-configure/SKILL.md +318 -0
  151. package/skills/sales-call-scoring-configure/assets/best-practice-competencies.json +67 -0
  152. package/skills/sales-call-scoring-configure/assets/ootb-competencies.json +58 -0
  153. package/skills/sales-call-scoring-configure/references/admin-communication.md +79 -0
  154. package/skills/sales-call-scoring-configure/references/competency-crud.md +130 -0
  155. package/skills/sales-call-scoring-configure/scripts/create-competency.sh +166 -0
  156. package/skills/sales-call-scoring-configure/scripts/create-custom-competency.sh +166 -0
  157. package/skills/sales-call-scoring-configure/scripts/edit-competency.sh +185 -0
  158. package/skills/sales-call-scoring-configure/scripts/edit-custom-competency.sh +190 -0
  159. package/skills/sales-call-scoring-configure/scripts/enable-call-scoring.sh +436 -0
  160. package/skills/sales-call-scoring-configure/scripts/get-competency.sh +72 -0
  161. package/skills/sales-call-scoring-configure/scripts/get-custom-competency.sh +78 -0
  162. package/skills/sales-call-scoring-configure/scripts/install-best-practice-competencies.sh +223 -0
  163. package/skills/sales-call-scoring-configure/scripts/install-ootb-competencies.sh +237 -0
  164. package/skills/sales-call-scoring-configure/scripts/list-competencies.sh +99 -0
  165. package/skills/sales-call-scoring-configure/scripts/shared/auth.sh +116 -0
  166. package/skills/sales-call-scoring-configure/scripts/shared/cap.sh +86 -0
  167. package/skills/sales-call-scoring-configure/scripts/shared/soap.sh +267 -0
  168. package/skills/sales-call-scoring-configure/scripts/shared/soql.sh +25 -0
  169. package/skills/sales-call-scoring-configure/scripts/toggle-competency.sh +112 -0
  170. package/skills/sales-call-scoring-configure/scripts/toggle-custom-competency.sh +125 -0
  171. package/skills/sales-call-scoring-configure/scripts/verify-ootb-competencies.sh +116 -0
  172. package/skills/service-concierge-portal-generate/references/portal-deploy-runbook.md +1 -0
  173. package/skills/service-de-channel-activate/SKILL.md +6 -5
  174. package/skills/service-de-channel-create/SKILL.md +3 -3
  175. package/skills/service-de-channel-routing-configure/SKILL.md +3 -3
  176. package/skills/service-de-channel-settings-configure/SKILL.md +195 -0
  177. package/skills/service-de-channel-settings-configure/references/channel-settings-facets.md +152 -0
  178. package/skills/{service-de-channel-consent-configure → service-de-channel-settings-configure}/references/gotchas.md +3 -3
  179. package/skills/{service-de-channel-consent-configure → service-de-channel-settings-configure}/references/language-keywords.md +4 -4
  180. package/skills/{service-de-channel-consent-configure → service-de-channel-settings-configure}/references/worked-examples.md +14 -14
  181. package/skills/service-de-headless-channel-configure/SKILL.md +6 -6
  182. package/skills/service-de-headless-channel-configure/references/worked-examples.md +1 -1
  183. package/skills/service-helpagent-coordinate/SKILL.md +3 -2
  184. package/skills/service-helpagent-coordinate/references/channel-voice.md +15 -4
  185. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +49 -31
  186. package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +71 -6
  187. package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +26 -4
  188. package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +35 -10
  189. package/skills/service-itsm-agentic-setup-cmdb-access-assign/references/mcp-invocation.md +25 -5
  190. package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +1 -1
  191. package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +5 -5
  192. package/skills/service-itsm-agentic-setup-cmdb-configure/references/mcp-invocation.md +1 -1
  193. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +2 -2
  194. package/skills/service-itsm-agentic-setup-cmdb-coordinate/examples/output-templates.md +1 -1
  195. package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +25 -15
  196. package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +8 -5
  197. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/report-format.md +4 -2
  198. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/workflow-detail.md +1 -1
  199. package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/render-report.mjs +29 -16
  200. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +8 -5
  201. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/report-format.md +4 -2
  202. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/workflow-detail.md +1 -1
  203. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/render-report.mjs +29 -16
  204. package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +138 -68
  205. package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +31 -15
  206. package/skills/service-itsm-agentic-setup-incident-management/references/incident-persona-psg.md +156 -0
  207. package/skills/service-itsm-agentic-setup-incident-management/references/incident-preferences.md +148 -0
  208. package/skills/service-itsm-agentic-setup-incident-management/references/major-incident-management.md +162 -0
  209. package/skills/service-itsm-agentic-setup-incident-management/references/service-mgmt-privilege.md +149 -0
  210. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +103 -89
  211. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone.json +2 -2
  212. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +21 -39
  213. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +3 -3
  214. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +18 -1
  215. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +63 -37
  216. package/skills/service-omni-attribute-routing-configure/SKILL.md +53 -0
  217. package/skills/service-omni-attribute-routing-configure/references/api-notes.md +7 -0
  218. package/skills/service-omni-attribute-routing-configure/scripts/configure-and-report.sh +224 -0
  219. package/skills/service-omni-attribute-routing-configure/scripts/tests/test_attribute_routing_contracts.py +137 -0
  220. package/skills/service-omni-channel-inventory-analyze/SKILL.md +96 -0
  221. package/skills/service-omni-channel-inventory-analyze/references/api-notes.md +52 -0
  222. package/skills/service-omni-channel-inventory-analyze/scripts/analyze.sh +185 -0
  223. package/skills/service-omni-channel-inventory-analyze/scripts/tests/_bootstrap.py +84 -0
  224. package/skills/service-omni-channel-inventory-analyze/scripts/tests/test_inventory_analyze_contracts.py +141 -0
  225. package/skills/service-omni-channel-limits-analyze/SKILL.md +70 -0
  226. package/skills/service-omni-channel-limits-analyze/references/api-notes.md +22 -0
  227. package/skills/service-omni-channel-limits-analyze/scripts/analyze.sh +159 -0
  228. package/skills/service-omni-channel-limits-analyze/scripts/tests/_bootstrap.py +87 -0
  229. package/skills/service-omni-channel-limits-analyze/scripts/tests/test_limits_analyze_contracts.py +99 -0
  230. package/skills/service-omni-channel-setup-coordinate/SKILL.md +12 -20
  231. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +55 -5
  232. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +38 -0
  233. package/skills/service-omni-command-center-analyze/SKILL.md +2 -2
  234. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
  235. package/skills/dx-org-manage/examples/snapshots/error_output.json +0 -9
  236. package/skills/dx-org-manage/examples/snapshots/success_output.json +0 -15
  237. package/skills/dx-org-manage/references/cli_flags.md +0 -67
  238. package/skills/dx-org-manage/references/creating-snapshot.md +0 -103
  239. package/skills/dx-org-manage/references/snapshot_usage.md +0 -74
  240. package/skills/experience-accessibility-validate/scripts/contrast-ratio.py +0 -153
  241. package/skills/experience-lwc-accessibility-jest-run/references/running-sa11y-jest-tests.md +0 -205
  242. package/skills/experience-ui-bundle-features-generate/scripts/verify-react-bundle.sh +0 -14
  243. /package/skills/experience-ui-bundle-features-generate/references/{conflict-resolution-schema.json → common/conflict-resolution-schema.json} +0 -0
  244. /package/skills/{platform-agentsetup-categories-fetch → platform-agenticsetup-categories-get}/references/api-response-schema.md +0 -0
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env bash
2
+ # Tests for compute_diff.py using fixture data.
3
+ # Validates diff computation, drift score, and report output.
4
+ #
5
+ # Usage: bash tests/test_compute_diff.sh
6
+ # Exit 0 on all-pass, 1 on any failure.
7
+
8
+ set -u
9
+
10
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ COMPUTE="$SCRIPT_DIR/../scripts/compute_diff.py"
12
+ FIXTURES="$SCRIPT_DIR/fixtures"
13
+ TMPDIR=$(mktemp -d)
14
+ trap "rm -rf $TMPDIR" EXIT
15
+
16
+ PASS=0
17
+ FAIL=0
18
+
19
+ pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
20
+ fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
21
+
22
+ # ============================================================
23
+ echo "=== Test 1: Produces JSON and markdown output ==="
24
+ # ============================================================
25
+
26
+ python3 "$COMPUTE" \
27
+ --org-a "$FIXTURES/org_a.json" \
28
+ --org-b "$FIXTURES/org_b.json" \
29
+ --output "$TMPDIR/diff" \
30
+ --format both \
31
+ --org-a-label "OrgA" \
32
+ --org-b-label "OrgB" >/dev/null 2>&1
33
+
34
+ if [[ -f "$TMPDIR/diff.json" ]]; then
35
+ pass "JSON output created"
36
+ else
37
+ fail "JSON output not created"
38
+ fi
39
+
40
+ if [[ -f "$TMPDIR/diff.md" ]]; then
41
+ pass "Markdown output created"
42
+ else
43
+ fail "Markdown output not created"
44
+ fi
45
+
46
+ # ============================================================
47
+ echo ""
48
+ echo "=== Test 2: JSON structure has required keys ==="
49
+ # ============================================================
50
+
51
+ if [[ -f "$TMPDIR/diff.json" ]]; then
52
+ for key in "metadata_stats" "permissions" "org_values" "drift"; do
53
+ if python3 -c "import json; d=json.load(open('$TMPDIR/diff.json')); assert '$key' in d" 2>/dev/null; then
54
+ pass "JSON has key '$key'"
55
+ else
56
+ fail "JSON missing key '$key'"
57
+ fi
58
+ done
59
+ fi
60
+
61
+ # ============================================================
62
+ echo ""
63
+ echo "=== Test 3: Drift score is computed correctly ==="
64
+ # ============================================================
65
+
66
+ if [[ -f "$TMPDIR/diff.json" ]]; then
67
+ python3 -c "
68
+ import json
69
+ d = json.load(open('$TMPDIR/diff.json'))['drift']
70
+ assert 0 <= d['overall'] <= 100, f'overall out of range: {d[\"overall\"]}'
71
+ assert 0 <= d['metadata'] <= 100
72
+ assert 0 <= d['permission'] <= 100
73
+ assert 0 <= d['profile'] <= 100
74
+ assert d['level'] in ('LOW', 'MODERATE', 'HIGH', 'CRITICAL')
75
+ print(f' overall={d[\"overall\"]}% level={d[\"level\"]}')
76
+ " 2>/dev/null && pass "Drift score valid and in range" || fail "Drift score invalid"
77
+ fi
78
+
79
+ # ============================================================
80
+ echo ""
81
+ echo "=== Test 4: Metadata diff detects known differences ==="
82
+ # ============================================================
83
+
84
+ if [[ -f "$TMPDIR/diff.json" ]]; then
85
+ python3 -c "
86
+ import json
87
+ stats = json.load(open('$TMPDIR/diff.json'))['metadata_stats']
88
+ apex = [s for s in stats if s['type'] == 'ApexClass'][0]
89
+ assert apex['a_only'] == 1, f'Expected 1 a_only ApexClass, got {apex[\"a_only\"]}'
90
+ assert apex['b_only'] == 1, f'Expected 1 b_only ApexClass, got {apex[\"b_only\"]}'
91
+ assert apex['shared'] == 1, f'Expected 1 shared ApexClass, got {apex[\"shared\"]}'
92
+ assert 'OnlyInA' in apex['a_only_names']
93
+ assert 'OnlyInB' in apex['b_only_names']
94
+ assert 'SharedClass' in apex['shared_names']
95
+ co = [s for s in stats if s['type'] == 'CustomObject'][0]
96
+ assert co['a_only'] == 1 and co['b_only'] == 0
97
+ " 2>/dev/null && pass "Metadata diff correct for fixtures" || fail "Metadata diff wrong"
98
+ fi
99
+
100
+ # ============================================================
101
+ echo ""
102
+ echo "=== Test 5: Permission diff detects known differences ==="
103
+ # ============================================================
104
+
105
+ if [[ -f "$TMPDIR/diff.json" ]]; then
106
+ python3 -c "
107
+ import json
108
+ p = json.load(open('$TMPDIR/diff.json'))['permissions']
109
+ assert 'ApiEnabled' in p['a_only'], f'ApiEnabled should be a_only'
110
+ assert 'ApexRest' in p['a_only'], f'ApexRest should be a_only'
111
+ assert 'DisabledInA' in p['b_only'], f'DisabledInA should be b_only'
112
+ assert 'OnlyInB' in p['b_only'], f'OnlyInB should be b_only'
113
+ assert p['shared_count'] == 1, f'Expected 1 shared perm, got {p[\"shared_count\"]}'
114
+ " 2>/dev/null && pass "Permission diff correct for fixtures" || fail "Permission diff wrong"
115
+ fi
116
+
117
+ # ============================================================
118
+ echo ""
119
+ echo "=== Test 6: Org values diff detects known differences ==="
120
+ # ============================================================
121
+
122
+ if [[ -f "$TMPDIR/diff.json" ]]; then
123
+ python3 -c "
124
+ import json
125
+ v = json.load(open('$TMPDIR/diff.json'))['org_values']
126
+ names = [d['name'] for d in v['diffs']]
127
+ assert 'OrgEdition' in names, 'OrgEdition should differ'
128
+ assert 'MaxCustomObjects' in names, 'MaxCustomObjects should differ'
129
+ assert 'DataStorage' in names, 'DataStorage should differ'
130
+ assert 'SharedValue' not in names, 'SharedValue should not differ'
131
+ assert v['total'] == 4, f'Expected 4 total values, got {v[\"total\"]}'
132
+ assert len(v['diffs']) == 3, f'Expected 3 diffs, got {len(v[\"diffs\"])}'
133
+ " 2>/dev/null && pass "Org values diff correct for fixtures" || fail "Org values diff wrong"
134
+ fi
135
+
136
+ # ============================================================
137
+ echo ""
138
+ echo "=== Test 7: Managed packages excluded from diff ==="
139
+ # ============================================================
140
+
141
+ if [[ -f "$TMPDIR/diff.json" ]]; then
142
+ python3 -c "
143
+ import json
144
+ stats = json.load(open('$TMPDIR/diff.json'))['metadata_stats']
145
+ apex = [s for s in stats if s['type'] == 'ApexClass'][0]
146
+ assert 'ManagedPkg' not in apex['a_only_names'], 'ManagedPkg should be excluded'
147
+ assert apex['a_count'] == 2, f'Expected 2 custom ApexClass in A (excl managed), got {apex[\"a_count\"]}'
148
+ " 2>/dev/null && pass "Managed packages excluded" || fail "Managed packages not excluded"
149
+ fi
150
+
151
+ # ============================================================
152
+ echo ""
153
+ echo "=== Test 8: Markdown report has required sections ==="
154
+ # ============================================================
155
+
156
+ if [[ -f "$TMPDIR/diff.md" ]]; then
157
+ for section in "Drift Score" "Summary Statistics" "Detailed Differences" "Org Permissions" "Org Values"; do
158
+ if grep -qF "$section" "$TMPDIR/diff.md"; then
159
+ pass "Markdown has section: $section"
160
+ else
161
+ fail "Markdown missing section: $section"
162
+ fi
163
+ done
164
+ fi
165
+
166
+ # ============================================================
167
+ echo ""
168
+ echo "=== Test 9: Markdown uses provided labels ==="
169
+ # ============================================================
170
+
171
+ if [[ -f "$TMPDIR/diff.md" ]]; then
172
+ if grep -qF "OrgA" "$TMPDIR/diff.md" && grep -qF "OrgB" "$TMPDIR/diff.md"; then
173
+ pass "Markdown uses custom labels OrgA/OrgB"
174
+ else
175
+ fail "Markdown not using custom labels"
176
+ fi
177
+ fi
178
+
179
+ # ============================================================
180
+ echo ""
181
+ echo "=== Test 10: Installed package diff ==="
182
+ # ============================================================
183
+
184
+ if [[ -f "$TMPDIR/diff.json" ]]; then
185
+ python3 -c "
186
+ import json
187
+ p = json.load(open('$TMPDIR/diff.json'))['installed_packages']
188
+ assert p['a_total'] == 3, f'Expected 3 packages in A, got {p[\"a_total\"]}'
189
+ assert p['b_total'] == 3, f'Expected 3 packages in B, got {p[\"b_total\"]}'
190
+ assert len(p['a_only']) == 1, f'Expected 1 a_only package, got {len(p[\"a_only\"])}'
191
+ assert p['a_only'][0]['namespace'] == 'apkg', f'Expected apkg, got {p[\"a_only\"][0][\"namespace\"]}'
192
+ assert len(p['b_only']) == 1, f'Expected 1 b_only package, got {len(p[\"b_only\"])}'
193
+ assert p['b_only'][0]['namespace'] == 'bpkg'
194
+ assert len(p['version_mismatches']) == 1, f'Expected 1 version mismatch, got {len(p[\"version_mismatches\"])}'
195
+ assert p['version_mismatches'][0]['namespace'] == 'vmpkg'
196
+ assert p['version_mismatches'][0]['a_version'] == '3.1'
197
+ assert p['version_mismatches'][0]['b_version'] == '4.0'
198
+ assert len(p['identical']) == 1, f'Expected 1 identical package, got {len(p[\"identical\"])}'
199
+ assert p['identical'][0]['namespace'] == 'sharedpkg'
200
+ " 2>/dev/null && pass "Package diff correct for fixtures" || fail "Package diff wrong"
201
+ fi
202
+
203
+ # ============================================================
204
+ echo ""
205
+ echo "=== Test 11: Markdown has installed packages section ==="
206
+ # ============================================================
207
+
208
+ if [[ -f "$TMPDIR/diff.md" ]]; then
209
+ if grep -qF "Installed Packages" "$TMPDIR/diff.md"; then
210
+ pass "Markdown has Installed Packages section"
211
+ else
212
+ fail "Markdown missing Installed Packages section"
213
+ fi
214
+ if grep -qF "Version Mismatch" "$TMPDIR/diff.md" && grep -qF "vmpkg" "$TMPDIR/diff.md"; then
215
+ pass "Markdown shows version mismatch details"
216
+ else
217
+ fail "Markdown missing version mismatch details"
218
+ fi
219
+ fi
220
+
221
+ # ============================================================
222
+ echo ""
223
+ echo "=== Test 12: License diff ==="
224
+ # ============================================================
225
+
226
+ if [[ -f "$TMPDIR/diff.json" ]]; then
227
+ python3 -c "
228
+ import json
229
+ lic = json.load(open('$TMPDIR/diff.json'))['licenses']
230
+ u = lic['user']
231
+ assert u['a_count'] == 3 and u['b_count'] == 3
232
+ assert len(u['a_only']) == 1, f'Expected 1 a_only user license, got {len(u[\"a_only\"])}'
233
+ assert u['a_only'][0]['Name'] == 'OnlyInA License'
234
+ assert len(u['b_only']) == 1
235
+ assert u['b_only'][0]['Name'] == 'OnlyInB License'
236
+ assert len(u['diffs']) == 1, f'Expected 1 user license diff, got {len(u[\"diffs\"])}'
237
+ assert u['diffs'][0]['name'] == 'Salesforce'
238
+ assert u['diffs'][0]['a_total'] == 10
239
+ assert u['diffs'][0]['b_total'] == 25
240
+ ps = lic['permission_set']
241
+ assert len(ps['diffs']) == 1
242
+ assert ps['diffs'][0]['name'] == 'SalesforceCPQ'
243
+ " 2>/dev/null && pass "License diff correct for fixtures" || fail "License diff wrong"
244
+ fi
245
+
246
+ # ============================================================
247
+ echo ""
248
+ echo "=== Test 13: Markdown has licenses section ==="
249
+ # ============================================================
250
+
251
+ if [[ -f "$TMPDIR/diff.md" ]]; then
252
+ if grep -qF "Licenses" "$TMPDIR/diff.md"; then
253
+ pass "Markdown has Licenses section"
254
+ else
255
+ fail "Markdown missing Licenses section"
256
+ fi
257
+ fi
258
+
259
+ # ============================================================
260
+ echo ""
261
+ echo "=== Test 14: Exits 1 on missing input file ==="
262
+ # ============================================================
263
+
264
+ python3 "$COMPUTE" \
265
+ --org-a "/nonexistent/file.json" \
266
+ --org-b "$FIXTURES/org_b.json" \
267
+ --output "$TMPDIR/fail" 2>/dev/null
268
+
269
+ if [[ $? -eq 1 ]]; then
270
+ pass "Exits 1 on missing input"
271
+ else
272
+ fail "Should exit 1 on missing input"
273
+ fi
274
+
275
+ # ============================================================
276
+ echo ""
277
+ echo "================================================"
278
+ echo "Results: $PASS passed, $FAIL failed"
279
+ echo "================================================"
280
+
281
+ if [[ $FAIL -gt 0 ]]; then
282
+ exit 1
283
+ fi
284
+ exit 0