Merge pull request #61 from wimvelzeboer/feature/TriggerBypass

Add bypass to TriggerHandler
This commit is contained in:
William Velzeboer
2024-03-01 18:53:23 +00:00
committed by GitHub
2 changed files with 75 additions and 8 deletions
@@ -32,6 +32,22 @@ public virtual with sharing class fflib_TriggerHandler
{ {
public static final System.Type DEFAUT_TRIGGERCONTEXT_TYPE = fflib_TriggerContext.class; public static final System.Type DEFAUT_TRIGGERCONTEXT_TYPE = fflib_TriggerContext.class;
/**
* Retains the trigger tracking configuration used for each domain
**/
private static Map<Type, fflib_SObjectDomain.TriggerEvent> triggerEventByClass;
/**
* Retain instance of Trigger Action classes implementing stateful
*/
@TestVisible
private static Map<Type, fflib_ITriggerAction> triggerActionStateByClass;
static
{
triggerEventByClass = new Map<Type, fflib_SObjectDomain.TriggerEvent>();
}
@TestVisible @TestVisible
protected System.Type triggerContextType protected System.Type triggerContextType
{ {
@@ -48,12 +64,6 @@ public virtual with sharing class fflib_TriggerHandler
protected fflib_ITriggerContext triggerContext; protected fflib_ITriggerContext triggerContext;
/**
* Retain instance of Trigger Action classes implementing stateful
*/
@TestVisible
private static Map<Type, fflib_ITriggerAction> triggerActionStateByClass;
/** /**
* Provides access to the trigger action configurations and allowing it to be mocked in unit-tests * Provides access to the trigger action configurations and allowing it to be mocked in unit-tests
*/ */
@@ -70,6 +80,16 @@ public virtual with sharing class fflib_TriggerHandler
execute(ctx); execute(ctx);
} }
public static fflib_SObjectDomain.TriggerEvent getTriggerEvent(Type triggerActionClass)
{
if(!triggerEventByClass.containsKey(triggerActionClass))
{
triggerEventByClass.put(triggerActionClass, new fflib_SObjectDomain.TriggerEvent());
}
return triggerEventByClass.get(triggerActionClass);
}
/** /**
* Tells the trigger handler in which trigger context it is running * Tells the trigger handler in which trigger context it is running
* *
@@ -109,7 +129,11 @@ public virtual with sharing class fflib_TriggerHandler
{ {
if (isValidExecutionContext(ctx, triggerActionConfig) == false if (isValidExecutionContext(ctx, triggerActionConfig) == false
|| ||
isValidSObjectType(triggerActionConfig, ctx) == false) continue; isValidSObjectType(triggerActionConfig, ctx) == false
||
!getTriggerEvent(triggerActionConfig.getImplementationType())
.isEnabled(ctx.isBefore(), ctx.isAfter(), ctx.isInsert(), ctx.isUpdate(), ctx.isDelete(), ctx.isUndelete()))
continue;
fflib_ITriggerAction triggerAction = getTriggerActionInstance(triggerActionConfig); fflib_ITriggerAction triggerAction = getTriggerActionInstance(triggerActionConfig);
@@ -256,7 +256,6 @@ private class fflib_TriggerHandlerTest
private static void itShouldUseTheStatefulTriggerActionClass() private static void itShouldUseTheStatefulTriggerActionClass()
{ {
fflib_LogEntry__c record = new fflib_LogEntry__c(LogLevel__c = 'INFO', Message__c = 'Unit Test'); fflib_LogEntry__c record = new fflib_LogEntry__c(LogLevel__c = 'INFO', Message__c = 'Unit Test');
List<fflib_LogEntry__c> records = new List<fflib_LogEntry__c> {record};
fflib_ApexMocks mocks = new fflib_ApexMocks(); fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_ITriggerAction triggerActionMock = (fflib_ITriggerAction) mocks.mock(fflib_ITriggerAction.class); fflib_ITriggerAction triggerActionMock = (fflib_ITriggerAction) mocks.mock(fflib_ITriggerAction.class);
@@ -296,6 +295,42 @@ private class fflib_TriggerHandlerTest
((fflib_ITriggerAction) mocks.verify(triggerActionMock)).doWork(); ((fflib_ITriggerAction) mocks.verify(triggerActionMock)).doWork();
} }
@IsTest
private static void itShouldNotExecuteBeforeDelete()
{
fflib_LogEntry__c record = new fflib_LogEntry__c(LogLevel__c = 'INFO', Message__c = 'Unit Test');
fflib_TriggerHandler.triggerActionStateByClass =
new Map<Type, fflib_ITriggerAction>{ MyTriggerBypassedAction.class => new MyTriggerBypassedAction() };
fflib_TriggerAction__mdt triggerAction = new fflib_TriggerAction__mdt(
ObjectType__c = null,
ObjectTypeAlternate__c = Schema.fflib_LogEntry__c.SObjectType.getDescribe().getName(),
BeforeDelete__c = true,
ImplementationType__c = 'fflib_TriggerHandlerTest.MyTriggerBypassedAction',
ExecutionContext__c = 'Realtime',
Stateful__c = true
);
fflib_TriggerHandler triggerHandler = new fflib_TriggerHandler();
String ctxClassName = triggerHandler.triggerContextType.getName() + '.Constructor';
fflib_TriggerContext ctx =
(fflib_TriggerContext)
((fflib_IDomainConstructor) Type.forName(ctxClassName).newInstance())
.construct(new List<fflib_LogEntry__c> {record});
ctx.triggerOperation = System.TriggerOperation.BEFORE_DELETE;
// WHEN a record is inserted
System.Test.startTest();
triggerHandler.addTriggerActionConfig(triggerAction);
// Setting bypass & run trigger
fflib_TriggerHandler.getTriggerEvent(MyTriggerBypassedAction.class).disableAll();
triggerHandler.setTriggerContext(ctx).run();
System.Test.stopTest();
}
public class MyTriggerAction extends fflib_TriggerAction // Todo - rename handler to action public class MyTriggerAction extends fflib_TriggerAction // Todo - rename handler to action
{ {
public override void onBeforeInsert() public override void onBeforeInsert()
@@ -305,4 +340,12 @@ private class fflib_TriggerHandlerTest
List<SObject> records = triggerContext.getRecords(); List<SObject> records = triggerContext.getRecords();
} }
} }
public class MyTriggerBypassedAction extends fflib_TriggerAction
{
public override void onBeforeDelete()
{
System.Assert.fail('It should not have reach this point');
}
}
} }