@salesforce/afv-skills 1.53.0 → 1.55.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.
- package/package.json +1 -1
- package/skills/dx-org-analyze/README.md +310 -0
- package/skills/dx-org-analyze/SKILL.md +261 -0
- package/skills/dx-org-analyze/references/collection-details.md +88 -0
- package/skills/dx-org-analyze/references/report-format.md +67 -0
- package/skills/dx-org-analyze/scripts/collect_org_data.py +823 -0
- package/skills/dx-org-analyze/scripts/compute_diff.py +1103 -0
- package/skills/dx-org-analyze/scripts/introspect_org.py +436 -0
- package/skills/dx-org-analyze/tests/README.md +46 -0
- package/skills/dx-org-analyze/tests/fixtures/org_a.json +76 -0
- package/skills/dx-org-analyze/tests/fixtures/org_b.json +70 -0
- package/skills/dx-org-analyze/tests/test_compute_diff.sh +284 -0
- package/skills/dx-org-analyze/tests/test_consistency.sh +428 -0
- package/skills/experience-design-validate/SKILL.md +163 -0
- package/skills/experience-design-validate/references/ai.md +54 -0
- package/skills/experience-design-validate/references/components.md +61 -0
- package/skills/experience-design-validate/references/craft.md +158 -0
- package/skills/experience-design-validate/references/data.md +59 -0
- package/skills/experience-design-validate/references/forms-flows.md +57 -0
- package/skills/experience-design-validate/references/interaction.md +53 -0
- package/skills/experience-design-validate/references/navigation.md +51 -0
- package/skills/experience-design-validate/references/performance.md +56 -0
- package/skills/experience-design-validate/references/records.md +60 -0
- package/skills/experience-design-validate/references/responsive.md +48 -0
- package/skills/experience-design-validate/references/scoring-rubric.md +257 -0
- package/skills/experience-design-validate/references/state.md +53 -0
- package/skills/experience-design-validate/references/trust.md +47 -0
- package/skills/experience-design-validate/references/usability.md +35 -0
- package/skills/experience-design-validate/references/visual-system.md +183 -0
- package/skills/service-agentforce-contact-center-coordinate/SKILL.md +170 -0
- package/skills/service-agentforce-contact-center-coordinate/assets/escalation-flow.flow-meta.xml +72 -0
- package/skills/service-agentforce-contact-center-coordinate/assets/omni-flow.flow-meta.xml +85 -0
- package/skills/service-agentforce-contact-center-coordinate/assets/report-template.md +52 -0
- package/skills/service-agentforce-contact-center-coordinate/references/agentforce-prerequisite.md +31 -0
- package/skills/service-agentforce-contact-center-coordinate/references/messaging_channel.md +76 -0
- package/skills/service-agentforce-contact-center-coordinate/references/number_management_api.md +78 -0
- package/skills/service-agentforce-contact-center-coordinate/references/omni-flow-routing.md +74 -0
- package/skills/service-agentforce-contact-center-coordinate/references/setup_summary.md +36 -0
- package/skills/service-agentforce-contact-center-coordinate/references/verification_and_errors.md +42 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/check-agentforce-prereq.sh +54 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/create-routing-flows.sh +49 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/create-voice-agent.sh +73 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/create-voice-channel.sh +66 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/fetch-numbers.sh +21 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/lib.sh +46 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/prepare-agent-workdir.sh +21 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/procure-number.sh +24 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/resolve-acc-queue.sh +27 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/resolve-channel-line.sh +37 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/resolve-flow-definition.sh +33 -0
- package/skills/service-agentforce-contact-center-coordinate/scripts/verify-number-live.sh +63 -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
|