Skip to content

Convert TriggerContext to OOB TriggerOperation #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 20 additions & 42 deletions src/classes/TriggerHandler.cls
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
public virtual class TriggerHandler {

@TestVisible
private static final String TRIGGER_CONTEXT_ERROR = 'Trigger handler called outside of Trigger execution';

// static map of handlername, times run() was invoked
private static Map<String, LoopCount> loopCountMap;
private static Set<String> bypassedHandlers;

// the current context of the trigger, overridable in tests
// the current operation of the trigger, overridable in tests
@TestVisible
private TriggerContext context;
private TriggerOperation operation;

// the current context of the trigger, overridable in tests
// the current operation of the trigger, overridable in tests
@TestVisible
private Boolean isTriggerExecuting;

Expand All @@ -20,7 +23,7 @@ public virtual class TriggerHandler {

// constructor
public TriggerHandler() {
this.setTriggerContext();
this.setTriggerOperation();
}

/***************************************
Expand All @@ -37,7 +40,7 @@ public virtual class TriggerHandler {
addToLoopCount();

// dispatch to the correct handler method
switch on this.context {
switch on this.operation {
when BEFORE_INSERT {
this.beforeInsert();
}
Expand Down Expand Up @@ -100,40 +103,23 @@ public virtual class TriggerHandler {
***************************************/

@TestVisible
private void setTriggerContext() {
this.setTriggerContext(null, false);
private void setTriggerOperation() {
this.setTriggerOperation(null, false);
}

@TestVisible
private void setTriggerContext(String ctx, Boolean testMode) {
private void setTriggerOperation(TriggerOperation op, Boolean testMode) {
if(!Trigger.isExecuting && !testMode) {
this.isTriggerExecuting = false;
return;
} else {
this.isTriggerExecuting = true;
}

if((Trigger.isExecuting && Trigger.isBefore && Trigger.isInsert) ||
(ctx != null && ctx == 'before insert')) {
this.context = TriggerContext.BEFORE_INSERT;
} else if((Trigger.isExecuting && Trigger.isBefore && Trigger.isUpdate) ||
(ctx != null && ctx == 'before update')){
this.context = TriggerContext.BEFORE_UPDATE;
} else if((Trigger.isExecuting && Trigger.isBefore && Trigger.isDelete) ||
(ctx != null && ctx == 'before delete')) {
this.context = TriggerContext.BEFORE_DELETE;
} else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isInsert) ||
(ctx != null && ctx == 'after insert')) {
this.context = TriggerContext.AFTER_INSERT;
} else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isUpdate) ||
(ctx != null && ctx == 'after update')) {
this.context = TriggerContext.AFTER_UPDATE;
} else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isDelete) ||
(ctx != null && ctx == 'after delete')) {
this.context = TriggerContext.AFTER_DELETE;
} else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isUndelete) ||
(ctx != null && ctx == 'after undelete')) {
this.context = TriggerContext.AFTER_UNDELETE;

if (Trigger.isExecuting) {
this.operation = Trigger.operationType;
} else if (op != null) {
this.operation = op;
}
}

Expand All @@ -153,8 +139,8 @@ public virtual class TriggerHandler {
// make sure this trigger should continue to run
@TestVisible
private Boolean validateRun() {
if(!this.isTriggerExecuting || this.context == null) {
throw new TriggerHandlerException('Trigger handler called outside of Trigger execution');
if(!this.isTriggerExecuting || this.operation == null) {
throw new TriggerHandlerException(TRIGGER_CONTEXT_ERROR);
}
return !TriggerHandler.bypassedHandlers.contains(getHandlerName());
}
Expand All @@ -165,10 +151,10 @@ public virtual class TriggerHandler {
}

/***************************************
* context methods
* operation methods
***************************************/

// context-specific methods for override
// operation-specific methods for override
@TestVisible
protected virtual void beforeInsert(){}
@TestVisible
Expand Down Expand Up @@ -226,14 +212,6 @@ public virtual class TriggerHandler {
}
}

// possible trigger contexts
@TestVisible
private enum TriggerContext {
BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE,
AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE,
AFTER_UNDELETE
}

// exception class
public class TriggerHandlerException extends Exception {}

Expand Down
22 changes: 10 additions & 12 deletions src/classes/TriggerHandler_Test.cls
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
@isTest
private class TriggerHandler_Test {

private static final String TRIGGER_CONTEXT_ERROR = 'Trigger handler called outside of Trigger execution';

private static String lastMethodCalled;

private static TriggerHandler_Test.TestHandler handler;
Expand All @@ -17,7 +15,7 @@ private class TriggerHandler_Test {
* unit tests
***************************************/

// contexts tests
// Operations tests

@isTest
static void testBeforeInsert() {
Expand Down Expand Up @@ -69,12 +67,12 @@ private class TriggerHandler_Test {
}

@isTest
static void testNonTriggerContext() {
static void testNonTriggerOperation() {
try{
handler.run();
System.assert(false, 'the handler ran but should have thrown');
} catch(TriggerHandler.TriggerHandlerException te) {
System.assertEquals(TRIGGER_CONTEXT_ERROR, te.getMessage(), 'the exception message should match');
System.assertEquals(TriggerHandler.TRIGGER_CONTEXT_ERROR, te.getMessage(), 'the exception message should match');
} catch(Exception e) {
System.assert(false, 'the exception thrown was not expected: ' + e.getTypeName() + ': ' + e.getMessage());
}
Expand Down Expand Up @@ -213,31 +211,31 @@ private class TriggerHandler_Test {
// modes for testing

private static void beforeInsertMode() {
handler.setTriggerContext('before insert', true);
handler.setTriggerOperation(TriggerOperation.BEFORE_INSERT, true);
}

private static void beforeUpdateMode() {
handler.setTriggerContext('before update', true);
handler.setTriggerOperation(TriggerOperation.BEFORE_UPDATE, true);
}

private static void beforeDeleteMode() {
handler.setTriggerContext('before delete', true);
handler.setTriggerOperation(TriggerOperation.BEFORE_DELETE, true);
}

private static void afterInsertMode() {
handler.setTriggerContext('after insert', true);
handler.setTriggerOperation(TriggerOperation.AFTER_INSERT, true);
}

private static void afterUpdateMode() {
handler.setTriggerContext('after update', true);
handler.setTriggerOperation(TriggerOperation.AFTER_UPDATE, true);
}

private static void afterDeleteMode() {
handler.setTriggerContext('after delete', true);
handler.setTriggerOperation(TriggerOperation.AFTER_DELETE, true);
}

private static void afterUndeleteMode() {
handler.setTriggerContext('after undelete', true);
handler.setTriggerOperation(TriggerOperation.AFTER_UNDELETE, true);
}

// test implementation of the TriggerHandler
Expand Down
21 changes: 3 additions & 18 deletions src/package.xml
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<members>TriggerHandler</members>
<members>TriggerHandler_Test</members>
<name>ApexClass</name>
</types>
<types>
<members>*</members>
<name>ApexComponent</name>
</types>
<types>
<members>*</members>
<name>ApexPage</name>
</types>
<types>
<members>*</members>
<name>ApexTrigger</name>
</types>
<types>
<members>*</members>
<name>StaticResource</name>
</types>
<version>55.0</version>
<version>62.0</version>
</Package>