@salesforce/afv-skills 1.1.0 → 1.3.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 +6 -5
- package/skills/accessing-webapp-data/SKILL.md +178 -0
- package/skills/agentforce-development/SKILL.md +427 -0
- package/skills/agentforce-development/assets/README-legacy.md +89 -0
- package/skills/agentforce-development/assets/agent-spec-template.md +90 -0
- package/skills/agentforce-development/assets/agents/README.md +45 -0
- package/skills/agentforce-development/assets/agents/hello-world.agent +60 -0
- package/skills/agentforce-development/assets/agents/multi-topic.agent +105 -0
- package/skills/agentforce-development/assets/agents/production-faq.agent +101 -0
- package/skills/agentforce-development/assets/agents/production-faq.bundle-meta.xml +4 -0
- package/skills/agentforce-development/assets/agents/simple-qa.agent +72 -0
- package/skills/agentforce-development/assets/apex/models-api-queueable.cls +225 -0
- package/skills/agentforce-development/assets/bundle-meta.xml +23 -0
- package/skills/agentforce-development/assets/components/apex-action.agent +52 -0
- package/skills/agentforce-development/assets/components/error-handling.agent +58 -0
- package/skills/agentforce-development/assets/components/escalation-setup.agent +169 -0
- package/skills/agentforce-development/assets/components/flow-action.agent +66 -0
- package/skills/agentforce-development/assets/components/n-ary-conditions.agent +110 -0
- package/skills/agentforce-development/assets/components/topic-with-actions.agent +40 -0
- package/skills/agentforce-development/assets/deterministic-routing.agent +166 -0
- package/skills/agentforce-development/assets/escalation-pattern.agent +209 -0
- package/skills/agentforce-development/assets/flow-action-lookup.agent +115 -0
- package/skills/agentforce-development/assets/hub-and-spoke.agent +104 -0
- package/skills/agentforce-development/assets/invocable-apex-template.cls +187 -0
- package/skills/agentforce-development/assets/local-info-agent-annotated.agent +355 -0
- package/skills/agentforce-development/assets/metadata/basic-prompt-template.promptTemplate-meta.xml +109 -0
- package/skills/agentforce-development/assets/metadata/genai-function-apex.xml +92 -0
- package/skills/agentforce-development/assets/metadata/genai-function-flow.xml +57 -0
- package/skills/agentforce-development/assets/metadata/genai-plugin.xml +72 -0
- package/skills/agentforce-development/assets/metadata/http-callout-flow.flow-meta.xml +348 -0
- package/skills/agentforce-development/assets/metadata/record-grounded-prompt.promptTemplate-meta.xml +136 -0
- package/skills/agentforce-development/assets/minimal-starter.agent +42 -0
- package/skills/agentforce-development/assets/patterns/README.md +254 -0
- package/skills/agentforce-development/assets/patterns/action-callbacks.agent +178 -0
- package/skills/agentforce-development/assets/patterns/advanced-input-bindings.agent +141 -0
- package/skills/agentforce-development/assets/patterns/bidirectional-routing.agent +156 -0
- package/skills/agentforce-development/assets/patterns/critical-input-collection.agent +244 -0
- package/skills/agentforce-development/assets/patterns/delegation-routing.agent +89 -0
- package/skills/agentforce-development/assets/patterns/lifecycle-events.agent +127 -0
- package/skills/agentforce-development/assets/patterns/llm-controlled-actions.agent +184 -0
- package/skills/agentforce-development/assets/patterns/multi-step-workflow.agent +282 -0
- package/skills/agentforce-development/assets/patterns/open-gate-routing.agent +286 -0
- package/skills/agentforce-development/assets/patterns/procedural-instructions.agent +273 -0
- package/skills/agentforce-development/assets/patterns/prompt-template-action.agent +188 -0
- package/skills/agentforce-development/assets/patterns/system-instruction-overrides.agent +293 -0
- package/skills/agentforce-development/assets/prompt-rag-search.agent +131 -0
- package/skills/agentforce-development/assets/template-multi-topic.agent +160 -0
- package/skills/agentforce-development/assets/template-single-topic.agent +81 -0
- package/skills/agentforce-development/assets/verification-gate.agent +208 -0
- package/skills/agentforce-development/references/action-prompt-templates.md +164 -0
- package/skills/agentforce-development/references/actions-reference.md +592 -0
- package/skills/agentforce-development/references/agent-access-guide.md +72 -0
- package/skills/agentforce-development/references/agent-design-and-spec-creation.md +1010 -0
- package/skills/agentforce-development/references/agent-metadata-and-lifecycle.md +575 -0
- package/skills/agentforce-development/references/agent-script-core-language.md +1218 -0
- package/skills/agentforce-development/references/agent-topic-map-diagrams.md +323 -0
- package/skills/agentforce-development/references/agent-user-setup.md +526 -0
- package/skills/agentforce-development/references/agent-validation-and-debugging.md +803 -0
- package/skills/agentforce-development/references/known-issues.md +353 -0
- package/skills/agentforce-development/references/minimal-examples.md +67 -0
- package/skills/agentforce-development/references/production-gotchas.md +279 -0
- package/skills/agentforce-development/references/salesforce-cli-for-agents.md +393 -0
- package/skills/agentforce-development/references/version-history.md +23 -0
- package/skills/building-webapp-data-visualization/SKILL.md +72 -0
- package/skills/building-webapp-data-visualization/implementation/bar-line-chart.md +316 -0
- package/skills/building-webapp-data-visualization/implementation/dashboard-layout.md +189 -0
- package/skills/building-webapp-data-visualization/implementation/donut-chart.md +181 -0
- package/skills/building-webapp-data-visualization/implementation/stat-card.md +150 -0
- package/skills/building-webapp-react-components/SKILL.md +96 -0
- package/skills/building-webapp-react-components/implementation/component.md +78 -0
- package/skills/building-webapp-react-components/implementation/header-footer.md +132 -0
- package/skills/building-webapp-react-components/implementation/page.md +93 -0
- package/skills/configuring-webapp-csp-trusted-sites/SKILL.md +90 -0
- package/skills/configuring-webapp-csp-trusted-sites/implementation/metadata-format.md +281 -0
- package/skills/configuring-webapp-metadata/SKILL.md +158 -0
- package/skills/creating-webapp/SKILL.md +141 -0
- package/skills/deploying-webapp-to-salesforce/SKILL.md +229 -0
- package/skills/exploring-webapp-graphql-schema/SKILL.md +149 -0
- package/skills/fetching-webapp-rest-api/SKILL.md +167 -0
- package/skills/{salesforce-custom-application → generating-custom-application}/SKILL.md +2 -4
- package/skills/{salesforce-custom-field → generating-custom-field}/SKILL.md +1 -5
- package/skills/{salesforce-custom-lightning-type → generating-custom-lightning-type}/SKILL.md +36 -2
- package/skills/{salesforce-custom-object → generating-custom-object}/SKILL.md +1 -1
- package/skills/generating-custom-tab/SKILL.md +154 -0
- package/skills/generating-experience-lwr-site/SKILL.md +196 -0
- package/skills/generating-experience-lwr-site/docs/bootstrap-template-byo-lwr.md +224 -0
- package/skills/generating-experience-lwr-site/docs/configure-content-brandingSet.md +131 -0
- package/skills/generating-experience-lwr-site/docs/configure-content-route.md +232 -0
- package/skills/generating-experience-lwr-site/docs/configure-content-themeLayout.md +141 -0
- package/skills/generating-experience-lwr-site/docs/configure-content-view.md +233 -0
- package/skills/generating-experience-lwr-site/docs/configure-guest-sharing-rules.md +42 -0
- package/skills/generating-experience-lwr-site/docs/handle-component-and-region-ids.md +27 -0
- package/skills/generating-experience-lwr-site/docs/handle-ui-components.md +215 -0
- package/skills/generating-experience-react-site/SKILL.md +67 -0
- package/skills/generating-experience-react-site/docs/configure-metadata-custom-site.md +41 -0
- package/skills/generating-experience-react-site/docs/configure-metadata-digital-experience-bundle.md +17 -0
- package/skills/generating-experience-react-site/docs/configure-metadata-digital-experience-config.md +21 -0
- package/skills/generating-experience-react-site/docs/configure-metadata-digital-experience.md +38 -0
- package/skills/generating-experience-react-site/docs/configure-metadata-network.md +72 -0
- package/skills/{salesforce-flexipage → generating-flexipage}/SKILL.md +86 -9
- package/skills/{salesforce-flow → generating-flow}/SKILL.md +3 -3
- package/skills/generating-fragment/SKILL.md +117 -0
- package/skills/generating-lightning-app/SKILL.md +423 -0
- package/skills/{salesforce-list-view → generating-list-view}/SKILL.md +1 -1
- package/skills/generating-permission-set/SKILL.md +174 -0
- package/skills/{salesforce-validation-rule → generating-validation-rule}/SKILL.md +1 -1
- package/skills/generating-webapp-graphql-mutation-query/SKILL.md +258 -0
- package/skills/generating-webapp-graphql-read-query/SKILL.md +253 -0
- package/skills/implementing-webapp-file-upload/SKILL.md +396 -0
- package/skills/installing-webapp-features/SKILL.md +210 -0
- package/skills/managing-webapp-agentforce-conversation-client/SKILL.md +186 -0
- package/skills/managing-webapp-agentforce-conversation-client/references/constraints.md +134 -0
- package/skills/managing-webapp-agentforce-conversation-client/references/examples.md +132 -0
- package/skills/managing-webapp-agentforce-conversation-client/references/style-tokens.md +101 -0
- package/skills/managing-webapp-agentforce-conversation-client/references/troubleshooting.md +57 -0
- package/skills/switching-org/SKILL.md +28 -0
- package/skills/using-webapp-graphql/SKILL.md +324 -0
- package/skills/using-webapp-graphql/shared-schema.graphqls +1150 -0
- package/skills/apex-class/SKILL.md +0 -253
- package/skills/apex-class/examples/AccountDeduplicationBatch.cls +0 -148
- package/skills/apex-class/examples/AccountSelector.cls +0 -193
- package/skills/apex-class/examples/AccountService.cls +0 -201
- package/skills/apex-class/templates/abstract.cls +0 -128
- package/skills/apex-class/templates/batch.cls +0 -125
- package/skills/apex-class/templates/domain.cls +0 -102
- package/skills/apex-class/templates/dto.cls +0 -108
- package/skills/apex-class/templates/exception.cls +0 -51
- package/skills/apex-class/templates/interface.cls +0 -25
- package/skills/apex-class/templates/queueable.cls +0 -92
- package/skills/apex-class/templates/schedulable.cls +0 -75
- package/skills/apex-class/templates/selector.cls +0 -92
- package/skills/apex-class/templates/service.cls +0 -69
- package/skills/apex-class/templates/utility.cls +0 -97
- package/skills/apex-test-class/SKILL.md +0 -101
- package/skills/apex-test-class/references/assertion-patterns.md +0 -209
- package/skills/apex-test-class/references/async-testing.md +0 -276
- package/skills/apex-test-class/references/mocking-patterns.md +0 -219
- package/skills/apex-test-class/references/test-data-factory.md +0 -176
- package/skills/deployment-readiness-check/SKILL.md +0 -257
- package/skills/deployment-readiness-check/assets/deployment_checklist.md +0 -286
- package/skills/deployment-readiness-check/references/rollback_procedures.md +0 -308
- package/skills/deployment-readiness-check/scripts/check_metadata.sh +0 -207
- package/skills/salesforce-custom-tab/SKILL.md +0 -78
- package/skills/salesforce-experience-site/SKILL.md +0 -178
- package/skills/salesforce-fragment/SKILL.md +0 -42
- package/skills/salesforce-lightning-app-build/SKILL.md +0 -254
- package/skills/salesforce-web-app-creating-records/SKILL.md +0 -84
- package/skills/salesforce-web-app-feature/SKILL.md +0 -70
- package/skills/salesforce-web-app-list-and-create-records/SKILL.md +0 -36
- package/skills/salesforce-web-application/SKILL.md +0 -34
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Custom exception for {describe when this exception is thrown}.
|
|
3
|
-
* Use this exception to signal domain-specific errors that callers
|
|
4
|
-
* can catch and handle distinctly from system exceptions.
|
|
5
|
-
* @author Generated by Apex Class Writer Skill
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* throw new {ClassName}('Account merge failed: duplicate detected.');
|
|
9
|
-
*
|
|
10
|
-
* // Wrap a caught exception
|
|
11
|
-
* try {
|
|
12
|
-
* // ... risky operation
|
|
13
|
-
* } catch (DmlException e) {
|
|
14
|
-
* throw new {ClassName}('DML failed during account merge: ' + e.getMessage());
|
|
15
|
-
* }
|
|
16
|
-
*/
|
|
17
|
-
public with sharing class {ClassName} extends Exception {
|
|
18
|
-
// Apex custom exceptions automatically inherit:
|
|
19
|
-
// - getMessage()
|
|
20
|
-
// - getCause()
|
|
21
|
-
// - getStackTraceString()
|
|
22
|
-
// - setMessage(String)
|
|
23
|
-
// - initCause(Exception)
|
|
24
|
-
//
|
|
25
|
-
// And support these constructor patterns:
|
|
26
|
-
// - new {ClassName}()
|
|
27
|
-
// - new {ClassName}('message')
|
|
28
|
-
// - new {ClassName}(causeException)
|
|
29
|
-
// - new {ClassName}('message', causeException)
|
|
30
|
-
//
|
|
31
|
-
// Note: Apex does NOT support custom constructors on Exception subclasses.
|
|
32
|
-
// To add context, use the message string or create a wrapper pattern:
|
|
33
|
-
//
|
|
34
|
-
// Example wrapper pattern (if you need structured error data):
|
|
35
|
-
//
|
|
36
|
-
// public class {ClassName}Detail {
|
|
37
|
-
// public String errorCode;
|
|
38
|
-
// public List<Id> failedRecordIds;
|
|
39
|
-
// public String detail;
|
|
40
|
-
//
|
|
41
|
-
// public {ClassName}Detail(String errorCode, List<Id> failedRecordIds, String detail) {
|
|
42
|
-
// this.errorCode = errorCode;
|
|
43
|
-
// this.failedRecordIds = failedRecordIds;
|
|
44
|
-
// this.detail = detail;
|
|
45
|
-
// }
|
|
46
|
-
//
|
|
47
|
-
// public override String toString() {
|
|
48
|
-
// return '[' + errorCode + '] ' + detail + ' (Records: ' + failedRecordIds + ')';
|
|
49
|
-
// }
|
|
50
|
-
// }
|
|
51
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Interface for {describe the capability or contract this interface defines}.
|
|
3
|
-
* Implement this interface to provide {describe what implementations do}.
|
|
4
|
-
* @author Generated by Apex Class Writer Skill
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* public class EmailNotificationService implements {InterfaceName} {
|
|
8
|
-
* public void execute(Map<String, Object> params) {
|
|
9
|
-
* // Implementation
|
|
10
|
-
* }
|
|
11
|
-
* }
|
|
12
|
-
*/
|
|
13
|
-
public interface {InterfaceName} {
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @description {Describe what this method should do}
|
|
17
|
-
* @param params {Describe the parameter}
|
|
18
|
-
* @return {Describe the return value}
|
|
19
|
-
*/
|
|
20
|
-
// TODO: Define interface methods
|
|
21
|
-
// Example:
|
|
22
|
-
// void execute(Map<String, Object> params);
|
|
23
|
-
// Boolean isEligible(SObject record);
|
|
24
|
-
// List<SObject> process(List<SObject> records);
|
|
25
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Queueable Apex class for {describe the async operation}.
|
|
3
|
-
* Accepts data through the constructor for stateful processing.
|
|
4
|
-
* Optionally implements Database.AllowsCallouts for external integrations.
|
|
5
|
-
* @author Generated by Apex Class Writer Skill
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* // Enqueue the job
|
|
9
|
-
* Id jobId = System.enqueueJob(new {ClassName}(recordIds));
|
|
10
|
-
*/
|
|
11
|
-
public with sharing class {ClassName} implements Queueable /*, Database.AllowsCallouts */ {
|
|
12
|
-
|
|
13
|
-
// ─── Constants ───────────────────────────────────────────────────────
|
|
14
|
-
private static final Integer MAX_CHAIN_DEPTH = 5;
|
|
15
|
-
|
|
16
|
-
// ─── Instance Variables (Stateful) ───────────────────────────────────
|
|
17
|
-
private Set<Id> recordIds;
|
|
18
|
-
private Integer chainDepth;
|
|
19
|
-
|
|
20
|
-
// ─── Constructors ────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @description Creates a new queueable job to process the specified records
|
|
24
|
-
* @param recordIds Set of record Ids to process
|
|
25
|
-
*/
|
|
26
|
-
public {ClassName}(Set<Id> recordIds) {
|
|
27
|
-
this(recordIds, 0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @description Creates a new queueable job with chain depth tracking
|
|
32
|
-
* @param recordIds Set of record Ids to process
|
|
33
|
-
* @param chainDepth Current depth in the queueable chain
|
|
34
|
-
*/
|
|
35
|
-
public {ClassName}(Set<Id> recordIds, Integer chainDepth) {
|
|
36
|
-
this.recordIds = recordIds ?? new Set<Id>();
|
|
37
|
-
this.chainDepth = chainDepth;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ─── Queueable Interface ─────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @description Executes the asynchronous work
|
|
44
|
-
* @param context The queueable context
|
|
45
|
-
*/
|
|
46
|
-
public void execute(QueueableContext context) {
|
|
47
|
-
if (this.recordIds.isEmpty()) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// TODO: Implement the async processing logic
|
|
53
|
-
// List<{SObject}> records = {SObject}Selector.selectByIds(this.recordIds);
|
|
54
|
-
// ... process records ...
|
|
55
|
-
|
|
56
|
-
// Chain to next job if there's more work and we haven't hit the depth limit
|
|
57
|
-
chainIfNeeded();
|
|
58
|
-
|
|
59
|
-
} catch (Exception e) {
|
|
60
|
-
handleError(context.getJobId(), e);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// ─── Private Helpers ─────────────────────────────────────────────────
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* @description Chains to the next queueable job if needed, with depth guard
|
|
68
|
-
*/
|
|
69
|
-
private void chainIfNeeded() {
|
|
70
|
-
// TODO: Determine if chaining is needed (e.g., remaining records to process)
|
|
71
|
-
Set<Id> remainingIds = new Set<Id>();
|
|
72
|
-
|
|
73
|
-
if (!remainingIds.isEmpty() && this.chainDepth < MAX_CHAIN_DEPTH) {
|
|
74
|
-
if (!Test.isRunningTest()) {
|
|
75
|
-
System.enqueueJob(new {ClassName}(remainingIds, this.chainDepth + 1));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @description Handles errors during execution
|
|
82
|
-
* @param jobId The async job Id
|
|
83
|
-
* @param e The exception that occurred
|
|
84
|
-
*/
|
|
85
|
-
private void handleError(Id jobId, Exception e) {
|
|
86
|
-
System.debug(LoggingLevel.ERROR,
|
|
87
|
-
'{ClassName} failed (Job: ' + jobId + '): ' +
|
|
88
|
-
e.getMessage() + '\n' + e.getStackTraceString()
|
|
89
|
-
);
|
|
90
|
-
// TODO: Persist error to a log object or send notification
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Schedulable Apex class for {describe the scheduled operation}.
|
|
3
|
-
* Delegates heavy processing to a Batch or Queueable job.
|
|
4
|
-
* Keep execute() lightweight — it should only launch other jobs.
|
|
5
|
-
* @author Generated by Apex Class Writer Skill
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* // Schedule to run daily at 2 AM
|
|
9
|
-
* String jobId = System.schedule(
|
|
10
|
-
* '{ClassName} - Daily',
|
|
11
|
-
* {ClassName}.CRON_DAILY_2AM,
|
|
12
|
-
* new {ClassName}()
|
|
13
|
-
* );
|
|
14
|
-
*
|
|
15
|
-
* // Or use the convenience method
|
|
16
|
-
* String jobId = {ClassName}.scheduleDaily();
|
|
17
|
-
*/
|
|
18
|
-
public with sharing class {ClassName} implements Schedulable {
|
|
19
|
-
|
|
20
|
-
// ─── CRON Expressions ────────────────────────────────────────────────
|
|
21
|
-
// Seconds Minutes Hours Day_of_month Month Day_of_week Optional_year
|
|
22
|
-
|
|
23
|
-
/** @description Runs daily at 2:00 AM */
|
|
24
|
-
public static final String CRON_DAILY_2AM = '0 0 2 * * ?';
|
|
25
|
-
|
|
26
|
-
/** @description Runs every weekday at 6:00 AM */
|
|
27
|
-
public static final String CRON_WEEKDAYS_6AM = '0 0 6 ? * MON-FRI';
|
|
28
|
-
|
|
29
|
-
/** @description Runs hourly at the top of the hour */
|
|
30
|
-
public static final String CRON_HOURLY = '0 0 * * * ?';
|
|
31
|
-
|
|
32
|
-
// ─── Schedulable Interface ───────────────────────────────────────────
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @description Entry point for the scheduled execution.
|
|
36
|
-
* Delegates to a Batch or Queueable for the actual work.
|
|
37
|
-
* @param sc The schedulable context
|
|
38
|
-
*/
|
|
39
|
-
public void execute(SchedulableContext sc) {
|
|
40
|
-
// Option A: Launch a Batch job
|
|
41
|
-
// Database.executeBatch(new {BatchClassName}(), 200);
|
|
42
|
-
|
|
43
|
-
// Option B: Launch a Queueable job
|
|
44
|
-
// System.enqueueJob(new {QueueableClassName}(params));
|
|
45
|
-
|
|
46
|
-
// TODO: Implement delegation to appropriate async job
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ─── Convenience Scheduling Methods ──────────────────────────────────
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @description Schedules this job to run daily at 2 AM
|
|
53
|
-
* @return The scheduled job Id
|
|
54
|
-
*/
|
|
55
|
-
public static String scheduleDaily() {
|
|
56
|
-
return System.schedule(
|
|
57
|
-
'{ClassName} - Daily 2AM',
|
|
58
|
-
CRON_DAILY_2AM,
|
|
59
|
-
new {ClassName}()
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @description Aborts this scheduled job by name
|
|
65
|
-
* @param jobName The name used when scheduling
|
|
66
|
-
*/
|
|
67
|
-
public static void abort(String jobName) {
|
|
68
|
-
for (CronTrigger ct : [
|
|
69
|
-
SELECT Id FROM CronTrigger
|
|
70
|
-
WHERE CronJobDetail.Name = :jobName
|
|
71
|
-
]) {
|
|
72
|
-
System.abortJob(ct.Id);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Selector class for {SObject} queries.
|
|
3
|
-
* Encapsulates all SOQL for {SObject} records.
|
|
4
|
-
* All methods return bulkified results (Lists or Maps).
|
|
5
|
-
* @author Generated by Apex Class Writer Skill
|
|
6
|
-
*/
|
|
7
|
-
public with sharing class {SObject}Selector {
|
|
8
|
-
|
|
9
|
-
// ─── Field Lists ─────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @description Returns the default set of fields to query for {SObject}.
|
|
13
|
-
* Centralizes field references to keep queries DRY.
|
|
14
|
-
* @return Comma-separated field list as a String
|
|
15
|
-
*/
|
|
16
|
-
private static String getDefaultFields() {
|
|
17
|
-
return String.join(
|
|
18
|
-
new List<String>{
|
|
19
|
-
'Id',
|
|
20
|
-
'Name',
|
|
21
|
-
'CreatedDate',
|
|
22
|
-
'LastModifiedDate'
|
|
23
|
-
// TODO: Add additional fields here
|
|
24
|
-
},
|
|
25
|
-
', '
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ─── Query Methods ───────────────────────────────────────────────────
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @description Selects {SObject} records by their Ids
|
|
33
|
-
* @param recordIds Set of {SObject} Ids to query
|
|
34
|
-
* @return List of {SObject} records matching the provided Ids
|
|
35
|
-
* @example
|
|
36
|
-
* Set<Id> ids = new Set<Id>{ '001xx000003DGbY' };
|
|
37
|
-
* List<{SObject}> results = {SObject}Selector.selectByIds(ids);
|
|
38
|
-
*/
|
|
39
|
-
public static List<{SObject}> selectByIds(Set<Id> recordIds) {
|
|
40
|
-
if (recordIds == null || recordIds.isEmpty()) {
|
|
41
|
-
return new List<{SObject}>();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return Database.query(
|
|
45
|
-
'SELECT ' + getDefaultFields() +
|
|
46
|
-
' FROM {SObject}' +
|
|
47
|
-
' WHERE Id IN :recordIds'
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @description Selects {SObject} records as a Map keyed by Id
|
|
53
|
-
* @param recordIds Set of {SObject} Ids to query
|
|
54
|
-
* @return Map of Id to {SObject}
|
|
55
|
-
*/
|
|
56
|
-
public static Map<Id, {SObject}> selectMapByIds(Set<Id> recordIds) {
|
|
57
|
-
return new Map<Id, {SObject}>(selectByIds(recordIds));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @description Selects {SObject} records by a specific field value
|
|
62
|
-
* @param fieldName API name of the field to filter on
|
|
63
|
-
* @param values Set of values to match
|
|
64
|
-
* @return List of matching {SObject} records
|
|
65
|
-
* @example
|
|
66
|
-
* List<{SObject}> results = {SObject}Selector.selectByField('Status__c', new Set<String>{ 'Active' });
|
|
67
|
-
*/
|
|
68
|
-
public static List<{SObject}> selectByField(String fieldName, Set<String> values) {
|
|
69
|
-
if (String.isBlank(fieldName) || values == null || values.isEmpty()) {
|
|
70
|
-
return new List<{SObject}>();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Validate field name to prevent SOQL injection
|
|
74
|
-
Schema.SObjectField field = Schema.SObjectType.{SObject}.fields.getMap().get(fieldName);
|
|
75
|
-
if (field == null) {
|
|
76
|
-
throw new QueryException('Invalid field name: ' + fieldName);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return Database.query(
|
|
80
|
-
'SELECT ' + getDefaultFields() +
|
|
81
|
-
' FROM {SObject}' +
|
|
82
|
-
' WHERE ' + String.escapeSingleQuotes(fieldName) + ' IN :values'
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ─── Exception ───────────────────────────────────────────────────────
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* @description Custom exception for query errors
|
|
90
|
-
*/
|
|
91
|
-
public class QueryException extends Exception {}
|
|
92
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Service class for {SObject} business logic.
|
|
3
|
-
* Follows separation of concerns: delegates queries to {SObject}Selector
|
|
4
|
-
* and SObject manipulation to {SObject}Domain where applicable.
|
|
5
|
-
* @author Generated by Apex Class Writer Skill
|
|
6
|
-
*/
|
|
7
|
-
public with sharing class {SObject}Service {
|
|
8
|
-
|
|
9
|
-
// ─── Constants ───────────────────────────────────────────────────────
|
|
10
|
-
private static final String ERROR_NULL_INPUT = 'Input cannot be null or empty.';
|
|
11
|
-
|
|
12
|
-
// ─── Public API ──────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @description {Describe the primary operation}
|
|
16
|
-
* @param recordIds Set of {SObject} Ids to process
|
|
17
|
-
* @return List of processed {SObject} records
|
|
18
|
-
* @throws {SObject}ServiceException if processing fails
|
|
19
|
-
* @example
|
|
20
|
-
* Set<Id> ids = new Set<Id>{ '001xx000003DGbY' };
|
|
21
|
-
* List<{SObject}> results = {SObject}Service.process{SObject}s(ids);
|
|
22
|
-
*/
|
|
23
|
-
public static List<{SObject}> process{SObject}s(Set<Id> recordIds) {
|
|
24
|
-
// Guard clause
|
|
25
|
-
if (recordIds == null || recordIds.isEmpty()) {
|
|
26
|
-
throw new {SObject}ServiceException(ERROR_NULL_INPUT);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Query via Selector
|
|
30
|
-
List<{SObject}> records = {SObject}Selector.selectByIds(recordIds);
|
|
31
|
-
|
|
32
|
-
// Apply business logic
|
|
33
|
-
// TODO: Implement business logic here
|
|
34
|
-
|
|
35
|
-
// DML
|
|
36
|
-
try {
|
|
37
|
-
update records;
|
|
38
|
-
} catch (DmlException e) {
|
|
39
|
-
throw new {SObject}ServiceException(
|
|
40
|
-
'Failed to update {SObject} records: ' + e.getMessage()
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return records;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// ─── Convenience Overloads ───────────────────────────────────────────
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @description Single-record convenience overload
|
|
51
|
-
* @param recordId The {SObject} Id to process
|
|
52
|
-
* @return The processed {SObject} record
|
|
53
|
-
*/
|
|
54
|
-
public static {SObject} process{SObject}(Id recordId) {
|
|
55
|
-
List<{SObject}> results = process{SObject}s(new Set<Id>{ recordId });
|
|
56
|
-
return results.isEmpty() ? null : results[0];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ─── Private Helpers ─────────────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
// TODO: Add private helper methods as needed
|
|
62
|
-
|
|
63
|
-
// ─── Exception ───────────────────────────────────────────────────────
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @description Custom exception for {SObject}Service errors
|
|
67
|
-
*/
|
|
68
|
-
public class {SObject}ServiceException extends Exception {}
|
|
69
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Utility class for {describe the category of utilities: String, Date, Collection, etc.}.
|
|
3
|
-
* All methods are static and side-effect-free (no SOQL, no DML).
|
|
4
|
-
* Private constructor prevents instantiation.
|
|
5
|
-
* @author Generated by Apex Class Writer Skill
|
|
6
|
-
*/
|
|
7
|
-
public with sharing class {ClassName} {
|
|
8
|
-
|
|
9
|
-
// ─── Private Constructor ─────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @description Prevents instantiation — use static methods only
|
|
13
|
-
*/
|
|
14
|
-
@TestVisible
|
|
15
|
-
private {ClassName}() {
|
|
16
|
-
// Utility class — do not instantiate
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// ─── Public Methods ──────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
// TODO: Add utility methods below. Examples:
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @description Safely converts a String to an Integer, returning a default if parsing fails
|
|
25
|
-
* @param value The String to parse
|
|
26
|
-
* @param defaultValue The fallback value if parsing fails
|
|
27
|
-
* @return The parsed Integer or the default value
|
|
28
|
-
* @example
|
|
29
|
-
* Integer result = {ClassName}.safeParseInteger('42', 0); // returns 42
|
|
30
|
-
* Integer result = {ClassName}.safeParseInteger('abc', 0); // returns 0
|
|
31
|
-
*/
|
|
32
|
-
public static Integer safeParseInteger(String value, Integer defaultValue) {
|
|
33
|
-
if (String.isBlank(value)) {
|
|
34
|
-
return defaultValue;
|
|
35
|
-
}
|
|
36
|
-
try {
|
|
37
|
-
return Integer.valueOf(value.trim());
|
|
38
|
-
} catch (TypeException e) {
|
|
39
|
-
return defaultValue;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @description Chunks a list into smaller sublists of the specified size.
|
|
45
|
-
* Useful for processing records in governor-limit-safe batches.
|
|
46
|
-
* @param items The list to chunk
|
|
47
|
-
* @param chunkSize The maximum size of each chunk
|
|
48
|
-
* @return A list of sublists, each containing up to chunkSize elements
|
|
49
|
-
* @example
|
|
50
|
-
* List<List<String>> chunks = {ClassName}.chunkList(myList, 200);
|
|
51
|
-
*/
|
|
52
|
-
public static List<List<Object>> chunkList(List<Object> items, Integer chunkSize) {
|
|
53
|
-
List<List<Object>> chunks = new List<List<Object>>();
|
|
54
|
-
if (items == null || items.isEmpty() || chunkSize <= 0) {
|
|
55
|
-
return chunks;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
List<Object> currentChunk = new List<Object>();
|
|
59
|
-
for (Object item : items) {
|
|
60
|
-
currentChunk.add(item);
|
|
61
|
-
if (currentChunk.size() == chunkSize) {
|
|
62
|
-
chunks.add(currentChunk);
|
|
63
|
-
currentChunk = new List<Object>();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!currentChunk.isEmpty()) {
|
|
68
|
-
chunks.add(currentChunk);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return chunks;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @description Extracts a Set of non-null field values from a list of SObjects
|
|
76
|
-
* @param records The SObject records to extract from
|
|
77
|
-
* @param fieldName The API name of the field to extract
|
|
78
|
-
* @return A Set of non-null String values
|
|
79
|
-
* @example
|
|
80
|
-
* Set<String> emails = {ClassName}.pluckStrings(contacts, 'Email');
|
|
81
|
-
*/
|
|
82
|
-
public static Set<String> pluckStrings(List<SObject> records, String fieldName) {
|
|
83
|
-
Set<String> values = new Set<String>();
|
|
84
|
-
if (records == null || String.isBlank(fieldName)) {
|
|
85
|
-
return values;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
for (SObject record : records) {
|
|
89
|
-
Object val = record.get(fieldName);
|
|
90
|
-
if (val != null) {
|
|
91
|
-
values.add(String.valueOf(val));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return values;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: apex-test-class
|
|
3
|
-
description: Apex test class generation with TestDataFactory patterns, bulk testing (200+ records), mocking strategies for callouts and async operations, and assertion best practices. Use when creating new Apex test classes, improving test coverage, refactoring existing tests, or implementing proper testing patterns for triggers, services, controllers, batch jobs, queueables, and integrations.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Apex Test Class Skill
|
|
7
|
-
|
|
8
|
-
## Core Principles
|
|
9
|
-
|
|
10
|
-
1. **Bulkify tests** - Always test with 200+ records to catch governor limit issues
|
|
11
|
-
2. **Isolate test data** - Use `@TestSetup` and TestDataFactory; never rely on org data
|
|
12
|
-
3. **Assert meaningfully** - Test behavior, not just coverage; include failure messages
|
|
13
|
-
4. **Mock external dependencies** - Use `HttpCalloutMock`, `Test.setMock()` for integrations
|
|
14
|
-
5. **Test negative paths** - Validate error handling, not just happy paths
|
|
15
|
-
|
|
16
|
-
## Test Class Structure
|
|
17
|
-
|
|
18
|
-
```apex
|
|
19
|
-
@IsTest
|
|
20
|
-
private class MyServiceTest {
|
|
21
|
-
|
|
22
|
-
@TestSetup
|
|
23
|
-
static void setupTestData() {
|
|
24
|
-
// Create shared test data using TestDataFactory
|
|
25
|
-
List<Account> accounts = TestDataFactory.createAccounts(200, true);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
@IsTest
|
|
29
|
-
static void shouldPerformExpectedBehavior_WhenValidInput() {
|
|
30
|
-
// Given: Setup specific test state
|
|
31
|
-
List<Account> accounts = [SELECT Id, Name FROM Account];
|
|
32
|
-
|
|
33
|
-
// When: Execute the code under test
|
|
34
|
-
Test.startTest();
|
|
35
|
-
MyService.processAccounts(accounts);
|
|
36
|
-
Test.stopTest();
|
|
37
|
-
|
|
38
|
-
// Then: Assert expected outcomes
|
|
39
|
-
List<Account> updated = [SELECT Id, Status__c FROM Account];
|
|
40
|
-
System.Assert.areEqual(200, updated.size(), 'All accounts should be processed');
|
|
41
|
-
for (Account acc : updated) {
|
|
42
|
-
System.Assert.areEqual('Processed', acc.Status__c, 'Status should be updated');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@IsTest
|
|
47
|
-
static void shouldThrowException_WhenInvalidInput() {
|
|
48
|
-
// Given
|
|
49
|
-
List<Account> emptyList = new List<Account>();
|
|
50
|
-
|
|
51
|
-
// When/Then
|
|
52
|
-
Test.startTest();
|
|
53
|
-
try {
|
|
54
|
-
MyService.processAccounts(emptyList);
|
|
55
|
-
System.Assert.fail('Expected MyCustomException to be thrown');
|
|
56
|
-
} catch (MyCustomException e) {
|
|
57
|
-
System.Assert.isTrue(e.getMessage().contains('cannot be empty'),
|
|
58
|
-
'Exception message should indicate empty input');
|
|
59
|
-
}
|
|
60
|
-
Test.stopTest();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Naming Convention
|
|
66
|
-
|
|
67
|
-
Use descriptive method names: `should[ExpectedBehavior]_When[Condition]`
|
|
68
|
-
|
|
69
|
-
Examples:
|
|
70
|
-
- `shouldCreateContact_WhenAccountIsActive`
|
|
71
|
-
- `shouldThrowException_WhenEmailIsInvalid`
|
|
72
|
-
- `shouldSendNotification_WhenOpportunityClosedWon`
|
|
73
|
-
- `shouldBypassTrigger_WhenRunningAsBatch`
|
|
74
|
-
|
|
75
|
-
## Test.startTest() / Test.stopTest()
|
|
76
|
-
|
|
77
|
-
Always wrap the code under test:
|
|
78
|
-
- Resets governor limits for accurate limit testing
|
|
79
|
-
- Executes async operations synchronously (queueables, batch, future)
|
|
80
|
-
- Fires scheduled jobs immediately
|
|
81
|
-
|
|
82
|
-
## Reference Files
|
|
83
|
-
|
|
84
|
-
Detailed patterns for specific scenarios:
|
|
85
|
-
|
|
86
|
-
- **[references/test-data-factory.md](references/test-data-factory.md)** - TestDataFactory class patterns and field defaults
|
|
87
|
-
- **[references/assertion-patterns.md](references/assertion-patterns.md)** - Assertion best practices and common pitfalls
|
|
88
|
-
- **[references/mocking-patterns.md](references/mocking-patterns.md)** - HttpCalloutMock, Test.setMock(), stubbing
|
|
89
|
-
- **[references/async-testing.md](references/async-testing.md)** - Batch, Queueable, Future, Scheduled job testing
|
|
90
|
-
|
|
91
|
-
## Quick Reference: What to Test
|
|
92
|
-
|
|
93
|
-
| Component | Key Test Scenarios |
|
|
94
|
-
|-----------|-------------------|
|
|
95
|
-
| Trigger | Bulk insert/update/delete, recursion, field changes |
|
|
96
|
-
| Service | Valid/invalid inputs, bulk operations, exceptions |
|
|
97
|
-
| Controller | Page load, action methods, view state |
|
|
98
|
-
| Batch | Start/execute/finish, chunking, error records |
|
|
99
|
-
| Queueable | Chaining, bulkification, error handling |
|
|
100
|
-
| Callout | Success response, error response, timeout |
|
|
101
|
-
| Scheduled | Execution, CRON validation |
|