From a99c1963e72e2ba76702b4124d898ed850b83ccc Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Tue, 22 Mar 2022 14:06:11 +0000 Subject: [PATCH 1/7] Added getChildren to the DmlRecord --- .../ortoo-core/default/classes/services/dml/DmlRecord.cls | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls index d430b40dec7..55fdf0c5902 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls @@ -163,6 +163,11 @@ public virtual inherited sharing class DmlRecord return this.childRecordsByType.get( childRecordType ); } + protected List getChildren( String childRecordType ) + { + return getChildDefiner( childRecordType ).getSobjects(); + } + /** * Sets the DmlDefinerOptions for the given child relationship. * From 0b6d11594d15f89a2a2092b70c8ce270661f8f40 Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Tue, 22 Mar 2022 14:18:34 +0000 Subject: [PATCH 2/7] Added docs and clarified name for DmlRecord method to get child sobjects --- .../default/classes/services/dml/DmlRecord.cls | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls index 55fdf0c5902..d5ff11073df 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls @@ -159,12 +159,23 @@ public virtual inherited sharing class DmlRecord @testVisible protected DmlDefiner getChildDefiner( String childRecordType ) { + Contract.requires( childRecordType != null, 'getChildDefiner called with a null childRecordType' ); + checkTypeIsValid( childRecordType ); return this.childRecordsByType.get( childRecordType ); } - protected List getChildren( String childRecordType ) + + /** + * Returns the Sobjects that represent the child records for the given relationship + * + * @param String The 'Type' that will identify the child relationship for which to return + * @return List The List representing the child records currently on this DmlRecord + */ + protected List getChildSobjects( String childRecordType ) { + Contract.requires( childRecordType != null, 'getChildSobjects called with a null childRecordType' ); + return getChildDefiner( childRecordType ).getSobjects(); } From f1b0c09b0732fc67f28b54cec92595262eb2b52b Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Tue, 22 Mar 2022 14:30:15 +0000 Subject: [PATCH 3/7] Added tests for DmlRecord.getChildSobjects --- .../classes/services/dml/DmlRecord.cls | 1 + .../services/dml/tests/DmlRecordTest.cls | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls index d5ff11073df..51055ae1b36 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls @@ -172,6 +172,7 @@ public virtual inherited sharing class DmlRecord * @param String The 'Type' that will identify the child relationship for which to return * @return List The List representing the child records currently on this DmlRecord */ + @testVisible protected List getChildSobjects( String childRecordType ) { Contract.requires( childRecordType != null, 'getChildSobjects called with a null childRecordType' ); diff --git a/framework/default/ortoo-core/default/classes/services/dml/tests/DmlRecordTest.cls b/framework/default/ortoo-core/default/classes/services/dml/tests/DmlRecordTest.cls index eeec1a08978..fb1151e9174 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/tests/DmlRecordTest.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/tests/DmlRecordTest.cls @@ -520,6 +520,61 @@ private without sharing class DmlRecordTest ortoo_Asserts.assertContains( 'Invalid', exceptionMessage, 'getChildDefiner, when given a child type that does not exist, will throw an exception' ); } + @isTest + private static void getChildSobjects_whenGivenAValidChildType_willReturnTheChildrenForThatType() // NOPMD: Test method name format + { + DmlRecord dmlRecord = new DmlRecord( new Account() ); + dmlRecord.addChildContext( 'Contacts', new DmlChildContext( Contact.AccountId, IChildRecordFinder.class ) ); + + List contacts = new List{ + new Contact( LastName = 'name1' ), + new Contact( LastName = 'name2' ) + }; + + Test.startTest(); + dmlRecord + .addChild( 'Contacts', new DmlRecord( contacts[0] ) ) + .addChild( 'Contacts', new DmlRecord( contacts[1] ) ); + + List got = dmlRecord.getChildSobjects( 'Contacts' ); + Test.stopTest(); + + System.assertEquals( contacts, got, 'getChildSobjects, when given a valid child type, will return the sobjects registered for that type' ); + } + + @isTest + private static void getChildSobjects_whenGivenAValidChildTypeThatHasNoChildren_willReturnAnEmptyList() // NOPMD: Test method name format + { + DmlRecord dmlRecord = new DmlRecord( new Account() ); + dmlRecord.addChildContext( 'Contacts', new DmlChildContext( Contact.AccountId, IChildRecordFinder.class ) ); + + Test.startTest(); + List got = dmlRecord.getChildSobjects( 'Contacts' ); + Test.stopTest(); + + System.assertEquals( new List(), got, 'getChildSobjects, when given a valid child type that has no children, will return an empty list' ); + } + + @isTest + private static void getChildSobjects_whenGivenAChildTypeThatDoesNotExist_willThrowAnException() // NOPMD: Test method name format + { + DmlRecord dmlRecord = new DmlRecord( new Account() ); + + Test.startTest(); + String exceptionMessage; + try + { + dmlRecord.getChildSobjects( 'Invalid' ); + } + catch ( Contract.AssertException e ) + { + exceptionMessage = e.getMessage(); + } + Test.stopTest(); + + ortoo_Asserts.assertContains( 'Invalid', exceptionMessage, 'getChildSobjects, when given a child type that does not exist, will throw an exception' ); + } + @isTest private static void setChildDmlOptions_whenGivenADmlDefinerOptions_willSetThatOnTheChildDefiner() // NOPMD: Test method name format { From 63c0a1871cc05a9fc5bc594cf8ceebb43edc7ef2 Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Wed, 23 Mar 2022 12:01:09 +0000 Subject: [PATCH 4/7] Added ability to find if a DmlDefiner will delete other records --- .../classes/services/dml/DmlChildContext.cls | 6 +++++ .../classes/services/dml/DmlDefiner.cls | 10 +++++++ .../services/dml/DmlDefinerOptions.cls | 10 +++++++ .../classes/services/dml/DmlRecord.cls | 6 +++++ .../dml/tests/DmlDefinerOptionsTest.cls | 26 +++++++++++++++++++ .../services/dml/tests/DmlDefinerTest.cls | 20 ++++++++++++++ 6 files changed, 78 insertions(+) diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlChildContext.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlChildContext.cls index f5a6be8ca14..75aa6567021 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlChildContext.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlChildContext.cls @@ -105,4 +105,10 @@ public inherited sharing class DmlChildContext uow.registerRelationship( child, relatedByField, parent ); } } + + @testVisible + private SobjectField getRelatedByField() + { + return relatedByField; + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlDefiner.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlDefiner.cls index 4edabfe2c85..e04639f6209 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlDefiner.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlDefiner.cls @@ -188,6 +188,16 @@ public inherited sharing class DmlDefiner return sobjects; } + /** + * States if this definer is configured to ensure that other records are deleted + * + * @return Boolean Will other records be deleted + */ + public Boolean getWillDeleteOtherRecords() { + Contract.assert( options != null, 'getWillDeleteOtherRecords was called when options was null' ); + return options.getWillDeleteOtherRecords(); + } + @testVisible private List getDmlRecords() { return recordsToDml; diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlDefinerOptions.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlDefinerOptions.cls index 58bb3709b41..8ebd3c091cf 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlDefinerOptions.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlDefinerOptions.cls @@ -43,4 +43,14 @@ public inherited sharing class DmlDefinerOptions return new DmlDefinerOptions() .setOtherRecordsMode( OtherRecordsOption.IGNORE_RECORDS ); } + + /** + * States if this definer will instruct to delete other records + * + * @return Boolean Should other records be deleted? + */ + public Boolean getWillDeleteOtherRecords() + { + return getOtherRecordsMode() == OtherRecordsOption.DELETE_RECORDS; + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls index 51055ae1b36..d331046d0d4 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/DmlRecord.cls @@ -283,4 +283,10 @@ public virtual inherited sharing class DmlRecord checkTypeIsValid( childRecordType ); return childContextsByType.get( childRecordType ); } + + @testVisible + private Boolean getWillDeleteOtherRecords( String childRecordType ) + { + return getChildDefiner( childRecordType )?.getWillDeleteOtherRecords(); + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerOptionsTest.cls b/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerOptionsTest.cls index 9bb441ad244..51cb51010ba 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerOptionsTest.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerOptionsTest.cls @@ -39,4 +39,30 @@ private without sharing class DmlDefinerOptionsTest ortoo_Asserts.assertContains( 'setOtherRecordsMode called with a null otherRecordsMode', exceptionMessage, 'setOtherRecordsMode, when called with null, will throw an exception' ); } + + @isTest + private static void getWillDeleteOtherRecords_whenRecordModeIsDelete_returnsTrue() // NOPMD: Test method name format + { + DmlDefinerOptions options = new DmlDefinerOptions(); + + Test.startTest(); + options.setOtherRecordsMode( DmlDefinerOptions.OtherRecordsOption.DELETE_RECORDS ); + Boolean got = options.getWillDeleteOtherRecords(); + Test.stopTest(); + + System.assertEquals( true, got, 'getWillDeleteOtherRecords, when the record mode is DELETE_RECORDS, will return true' ); + } + + @isTest + private static void getWillDeleteOtherRecords_whenRecordModeIsIgnore_returnsFalse() // NOPMD: Test method name format + { + DmlDefinerOptions options = new DmlDefinerOptions(); + + Test.startTest(); + options.setOtherRecordsMode( DmlDefinerOptions.OtherRecordsOption.IGNORE_RECORDS ); + Boolean got = options.getWillDeleteOtherRecords(); + Test.stopTest(); + + System.assertEquals( false, got, 'getWillDeleteOtherRecords, when the record mode is IGNORE_RECORDS, will return false' ); + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerTest.cls b/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerTest.cls index 8a38bcfa890..69ee840dab9 100644 --- a/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerTest.cls +++ b/framework/default/ortoo-core/default/classes/services/dml/tests/DmlDefinerTest.cls @@ -311,4 +311,24 @@ private without sharing class DmlDefinerTest ortoo_Asserts.assertContains( 'addPreSaveAction called with a null action', exceptionMessage, 'addPreSaveAction, when given null, will throw an exception' ); } + + @isTest + private static void getWillDeleteOtherRecords_willReturnTheValueFromTheDefiner() // NOPMD: Test method name format + { + DmlDefiner dmlDefiner = new DmlDefiner(); + + Amoss_Instance optionsController = new Amoss_Instance( DmlDefinerOptions.class ); + optionsController + .expects( 'getWillDeleteOtherRecords' ) + .returning( true ); + + Test.startTest(); + dmlDefiner.setOptions( (DmlDefinerOptions)optionsController.generateDouble() ); + Boolean got = dmlDefiner.getWillDeleteOtherRecords(); + Test.stopTest(); + + optionsController.verify(); + + System.assertEquals( true, got, 'getWillDeleteOtherRecords, will call getWillDeleteOtherRecords on the options and return the result' ); + } } \ No newline at end of file From 5fe2224ffe3bae3957abd99619ae110372bc7f53 Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Wed, 23 Mar 2022 15:26:49 +0000 Subject: [PATCH 5/7] Added the ability to get the Id of a persisted fabricatedSobject --- .../classes/sfab_FabricatedSObject.cls | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/framework/default/sobject-fabricator/classes/sfab_FabricatedSObject.cls b/framework/default/sobject-fabricator/classes/sfab_FabricatedSObject.cls index ce1c455d7c6..ec6971f7acf 100644 --- a/framework/default/sobject-fabricator/classes/sfab_FabricatedSObject.cls +++ b/framework/default/sobject-fabricator/classes/sfab_FabricatedSObject.cls @@ -25,6 +25,8 @@ public virtual class sfab_FabricatedSObject { public class NodeNotSetException extends Exception {} + Sobject persistedSobject; + /** * Constructs a FabricatedSObject of the given type. * @@ -35,6 +37,12 @@ public virtual class sfab_FabricatedSObject { ortoo_FabricatedSObjectRegister.registerObject( this ); } + public Id persistedId { + get { + return persistedSobject?.Id; + } + } + /** * Constructs a FabricatedSObject of the given type, and then sets the fields specified in the given map. * @@ -306,9 +314,9 @@ public virtual class sfab_FabricatedSObject { * * @return SObject - The built SObject */ - public SObject toPersistableSobject() - { - return internalToSobject( true ); + public SObject toPersistableSobject() { + persistedSobject = internalToSobject( true ); + return persistedSobject; } private Sobject internalToSobject( Boolean persistable ) From 0d88df9f6c8f65f025d7813f98d0489c0e31724c Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Thu, 24 Mar 2022 13:32:56 +0000 Subject: [PATCH 6/7] Added ability to add sub criteria without specifying the logic condition This allows for composite criteria to be created Added StringUtils.cut for safe, simple cutting the length of strings Added clearance of the object register when fabricated Sobjects are persisted. Allows multiple persists to be called --- .../classes/criteria/fflib_Criteria.cls | 28 +++++++- .../classes/tests/fflib_CriteriaTest.cls | 17 +++++ .../fflib-extension/ortoo_Criteria.cls | 27 ++++++++ .../tests/ortoo_CriteriaTest.cls | 42 ++++++++++++ .../default/classes/utils/StringUtils.cls | 20 ++++++ .../classes/utils/tests/StringUtilsTest.cls | 68 +++++++++++++++++++ 6 files changed, 200 insertions(+), 2 deletions(-) diff --git a/framework/default/fflib-apex-extensions/default/classes/criteria/fflib_Criteria.cls b/framework/default/fflib-apex-extensions/default/classes/criteria/fflib_Criteria.cls index 6493afe008a..2a31c56c890 100755 --- a/framework/default/fflib-apex-extensions/default/classes/criteria/fflib_Criteria.cls +++ b/framework/default/fflib-apex-extensions/default/classes/criteria/fflib_Criteria.cls @@ -125,8 +125,7 @@ public virtual with sharing class fflib_Criteria public virtual fflib_Criteria addOrCriteria(fflib_Criteria subCriteria) { subCriteria.orCriteria(); - subCriteria.setEmbraced(true); - evaluators.add(subCriteria); + addCriteria( subCriteria ); return this; } @@ -152,6 +151,31 @@ public virtual with sharing class fflib_Criteria public virtual fflib_Criteria addAndCriteria(fflib_Criteria subCriteria) { subCriteria.andCriteria(); + addCriteria( subCriteria ); + return this; + } + + /** + * Adds a sub criteria, not altering the join (AND / OR) + * + * @param subCriteria The condition of the sub criteria + * + * @return An instance of itself to enable method chaining + * + * @example + * new fflib_Criteria() + * .orCriteria() + * .equalTo(Account.Name, 'Example') + * .addCriteria( + * new fflib_Criteria() + * .equalTo(Account.AccountNumber, '0001') + * .equalTo(Account.ShippingCountry, 'USA')) + * + * Evaluates: + * Name = 'Example' OR (AccountNumber = '0001' AND ShippingCountry = 'USA') + */ + public fflib_Criteria addCriteria(fflib_Criteria subCriteria) + { subCriteria.setEmbraced(true); evaluators.add(subCriteria); return this; diff --git a/framework/default/fflib-apex-extensions/default/classes/tests/fflib_CriteriaTest.cls b/framework/default/fflib-apex-extensions/default/classes/tests/fflib_CriteriaTest.cls index f84b9b0733f..90e0f9be041 100755 --- a/framework/default/fflib-apex-extensions/default/classes/tests/fflib_CriteriaTest.cls +++ b/framework/default/fflib-apex-extensions/default/classes/tests/fflib_CriteriaTest.cls @@ -462,6 +462,23 @@ private with sharing class fflib_CriteriaTest ); } + @IsTest + static void itShouldEvaluateAddCondition_First() + { + System.assert( + new fflib_Criteria() + .orCriteria() + .equalTo(Account.Name, A_STRING) + .equalTo(Account.Name, ANOTHER_STRING) + .addCriteria( + new fflib_Criteria() + .equalTo(Account.Name, HELLO_WORLD) + .equalTo(Account.AccountNumber, '002') + ) + .evaluate(new Account(Name = ANOTHER_STRING)) + ); + } + @IsTest static void itShouldEvaluateAddAndCondition_First() { diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_Criteria.cls b/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_Criteria.cls index 77978eaccb1..2a1fbffafca 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_Criteria.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_Criteria.cls @@ -100,6 +100,33 @@ public inherited sharing virtual class ortoo_Criteria implements ISearchCriteria return this; } + /** + * Adds a sub-criteria + * + * @param ortoo_Criteria The condition of the sub criteria + * @return ortoo_Criteria Itself, allowing for a fluent interface + * + * @example + * new ortoo_Criteria() + * .orCriteria() + * .equalTo(Account.Name, 'Example') + * .addCriteria( + * new ortoo_Criteria() + * .equalTo(Account.AccountNumber, '0001') + * .equalTo(Account.ShippingCountry, 'USA')) + * + * Evaluates: + * Name = 'Example' OR (AccountNumber = '0001' AND ShippingCountry = 'USA') + */ + public ortoo_Criteria addCriteria( ortoo_Criteria subCriteria ) + { + Contract.requires( subCriteria != null, 'addCriteria called with a null subCriteria' ); + Contract.requires( subCriteria.criteria != null, 'addCriteria called with a subCriteria that has no criteria defined' ); + + criteria.addCriteria( subCriteria.criteria ); + return this; + } + /** * Adds a sub-criteria with AND comparator * diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_CriteriaTest.cls b/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_CriteriaTest.cls index 15ca978aee8..33df156ef6f 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_CriteriaTest.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_CriteriaTest.cls @@ -94,6 +94,48 @@ private without sharing class ortoo_CriteriaTest System.assertEquals( expected, got, 'andAndCriteria, when given sub criteria, will add the subcriteria set as AND criteria' ); } + @isTest + private static void andCriteria_whenGivenSubCriteria_addsTheSubCriteriaSetAsOriginalSpec() // NOPMD: Test method name format + { + ortoo_Criteria criteria = new ortoo_Criteria(); + + Test.startTest(); + String got = criteria + .equalTo(Account.Name, 'Example') + .addCriteria( + new ortoo_Criteria() + .andCriteria() + .equalTo(Account.AccountNumber, '0001') + .equalTo(Account.AccountNumber, '0002')) + .toSoql(); + Test.stopTest(); + + String expected = 'Name=\'Example\' AND (AccountNumber=\'0001\' AND AccountNumber=\'0002\')'; + + System.assertEquals( expected, got, 'andCriteria, when given sub criteria, will add the subcriteria set as originally configured (was and)' ); + } + + @isTest + private static void andCriteria_whenGivenSubCriteria_addsTheSubCriteriaSetAsOriginalSpec_2() // NOPMD: Test method name format + { + ortoo_Criteria criteria = new ortoo_Criteria(); + + Test.startTest(); + String got = criteria + .equalTo(Account.Name, 'Example') + .addCriteria( + new ortoo_Criteria() + .orCriteria() + .equalTo(Account.AccountNumber, '0001') + .equalTo(Account.AccountNumber, '0002')) + .toSoql(); + Test.stopTest(); + + String expected = 'Name=\'Example\' AND (AccountNumber=\'0001\' OR AccountNumber=\'0002\')'; + + System.assertEquals( expected, got, 'andCriteria, when given sub criteria, will add the subcriteria set as originally configured (was or)' ); + } + @isTest private static void formulaCriteria_whenGivenCriteria_addsTheCriteriaInLineWithTheFormula() // NOPMD: Test method name format { diff --git a/framework/default/ortoo-core/default/classes/utils/StringUtils.cls b/framework/default/ortoo-core/default/classes/utils/StringUtils.cls index 9647fbe3787..7c829dcd090 100644 --- a/framework/default/ortoo-core/default/classes/utils/StringUtils.cls +++ b/framework/default/ortoo-core/default/classes/utils/StringUtils.cls @@ -115,4 +115,24 @@ public inherited sharing class StringUtils return String.join( ListUtils.convertToListOfStrings( listOfObjects ), delimiter ); } + + /** + * Given a String, will safely cut it to the desired length, returning the original string if it is already shorter + * + * @param String The string to cut + * @param Integer The length to cut the string to + * @return String The cut string + */ + public static String cut( String originalString, Integer length ) + { + Contract.requires( originalString != null, 'cut called with a null originalString' ); + Contract.requires( length != null, 'cut called with a null length' ); + Contract.requires( length >= 0, 'cut called with a negative length' ); + + if ( originalString.length() < length ) + { + return originalString; + } + return originalString.substring( 0, length ); + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/utils/tests/StringUtilsTest.cls b/framework/default/ortoo-core/default/classes/utils/tests/StringUtilsTest.cls index 6bb167deb21..31d3c5ad251 100644 --- a/framework/default/ortoo-core/default/classes/utils/tests/StringUtilsTest.cls +++ b/framework/default/ortoo-core/default/classes/utils/tests/StringUtilsTest.cls @@ -377,6 +377,74 @@ private without sharing class StringUtilsTest ortoo_Asserts.assertContains( 'convertListToDelimitedString called with an empty delimiter', exceptionMessage, 'convertListToDelimitedString, when passed an empty delimiter, will throw an exception' ); } + @isTest + private static void cut_whenGivenALongString_cutsItToTheDesiredLength() // NOPMD: Test method name format + { + String got = StringUtils.cut( 'theoriginalstring', 5 ); + System.assertEquals( 'theor', got, 'cut, when given a string longer than the desired length, will cut it to the specified length' ); + } + + @isTest + private static void cut_whenGivenAShortString_returnsTheOriginal() // NOPMD: Test method name format + { + String got = StringUtils.cut( 'short', 10 ); + System.assertEquals( 'short', got, 'cut, when given a string shorter than the desired length, will return the original string' ); + } + + @isTest + private static void cut_whenPassedANullString_throwsAnException() // NOPMD: Test method name format + { + Test.startTest(); + String exceptionMessage; + try + { + StringUtils.cut( null, 5 ); + } + catch ( Contract.RequiresException e ) + { + exceptionMessage = e.getMessage(); + } + Test.stopTest(); + + ortoo_Asserts.assertContains( 'cut called with a null originalString', exceptionMessage, 'cut, when passed a null string, will throw an exception' ); + } + + @isTest + private static void cut_whenPassedANullLength_throwsAnException() // NOPMD: Test method name format + { + Test.startTest(); + String exceptionMessage; + try + { + StringUtils.cut( 'string', null ); + } + catch ( Contract.RequiresException e ) + { + exceptionMessage = e.getMessage(); + } + Test.stopTest(); + + ortoo_Asserts.assertContains( 'cut called with a null length', exceptionMessage, 'cut, when passed a null length, will throw an exception' ); + } + + @isTest + private static void cut_whenPassedANegativeLength_throwsAnException() // NOPMD: Test method name format + { + Test.startTest(); + String exceptionMessage; + try + { + StringUtils.cut( 'string', -3 ); + } + catch ( Contract.RequiresException e ) + { + exceptionMessage = e.getMessage(); + } + Test.stopTest(); + + ortoo_Asserts.assertContains( 'cut called with a negative length', exceptionMessage, 'cut, when passed a negative length, will throw an exception' ); + } + private inherited sharing class StringableThing { String name; public StringableThing( String name ) From a1c58d909759c7dcecef4366fdc79326b947e2e6 Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Thu, 24 Mar 2022 13:33:09 +0000 Subject: [PATCH 7/7] Added clearance of the object register when fabricated Sobjects are persisted. Allows multiple persists to be called --- .../ortoo_FabricatedSObjectRegister.cls | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/framework/default/sobject-fabricator/classes/ortoo_FabricatedSObjectRegister.cls b/framework/default/sobject-fabricator/classes/ortoo_FabricatedSObjectRegister.cls index 12761b57f7f..d282b9495d6 100644 --- a/framework/default/sobject-fabricator/classes/ortoo_FabricatedSObjectRegister.cls +++ b/framework/default/sobject-fabricator/classes/ortoo_FabricatedSObjectRegister.cls @@ -75,10 +75,15 @@ public class ortoo_FabricatedSObjectRegister { @testVisible private inherited sharing class RegisterInstance { - private List objectRegister = new List(); - private List relationships = new List(); + private List objectRegister; + private List relationships; private Map sobjectsByFabricated; - private DirectedGraph graph = new DirectedGraph(); + private DirectedGraph graph; + + public RegisterInstance() + { + initialise(); + } public void registerObject( sfab_FabricatedSObject objectToRegister ) { @@ -110,6 +115,15 @@ public class ortoo_FabricatedSObjectRegister { registerInserts( uow ); registerRelationships( uow ); uow.commitWork(); + + initialise(); + } + + private void initialise() + { + objectRegister = new List(); + relationships = new List(); + graph = new DirectedGraph(); } @testVisible