diff --git a/TODO.txt b/TODO.txt index 9e8494d0699..a1db6f45656 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,7 @@ TODO: - * Combine the DateTimeUtils and DateLiterals where appropriate * Document TestDateTimeUtils and how to set now and today * Add 'maximum age' into CachedSoqlExecutor + * Add 'maximum age' into DynamicSelector * Consider a superclass for OrgCache and SessionCache? diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/CacheEntry.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/CacheEntry.cls index a6cdd75f382..8db4d014fd0 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/CacheEntry.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/CacheEntry.cls @@ -9,14 +9,14 @@ public inherited sharing class CacheEntry { get { - return DateTimeUtils.getEpochTime() - this.createdOnEpoch; + return ortoo_DateLiterals.epochTime - this.createdOnEpoch; } } public CacheEntry( Object value ) { this.value = value; - this.createdOnEpoch = DateTimeUtils.getEpochTime(); + this.createdOnEpoch = ortoo_DateLiterals.epochTime; } public Boolean isYoungerThanOrEqualTo( Long compareAgeInSeconds ) diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls index 1749af0f352..e597b0c220b 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/OrgCache.cls @@ -75,7 +75,7 @@ public inherited sharing class OrgCache implements ICacheAdaptor Long maximumAgeInSeconds; if ( minimumDateTime != null ) { - maximumAgeInSeconds = DateTimeUtils.getEpochTime() - DateTimeUtils.getEpochTime( minimumDateTime ); + maximumAgeInSeconds = ortoo_DateLiterals.epochTime - DateTimeUtils.convertToEpochTime( minimumDateTime ); } return get( key, maximumAgeInSeconds ); } diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls b/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls index d14f295dea1..3992f683777 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/caching/SessionCache.cls @@ -52,7 +52,7 @@ public inherited sharing class SessionCache implements ICacheAdaptor Long maximumAgeInSeconds; if ( minimumDateTime != null ) { - maximumAgeInSeconds = DateTimeUtils.getEpochTime() - DateTimeUtils.getEpochTime( minimumDateTime ); + maximumAgeInSeconds = ortoo_DateLiterals.epochTime - DateTimeUtils.convertToEpochTime( minimumDateTime ); } return get( key, maximumAgeInSeconds ); } diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_DateLiterals.cls b/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_DateLiterals.cls index 6ce42936a58..1f59c3d128f 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_DateLiterals.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/ortoo_DateLiterals.cls @@ -19,8 +19,12 @@ public inherited sharing class ortoo_DateLiterals private interface Literal extends fflib_Criteria.Literal {} private interface Comparable extends fflib_Comparator.Comparable {} - // TODO: document - // TODO: test + /** + * Representation of 'today' that is to be used whenever a reference is required. + * Should be used in place of System.today or Date.today + * + * The existance allows for the calendar to be re-set in Unit Tests. + */ public static Date today { get @@ -34,8 +38,12 @@ public inherited sharing class ortoo_DateLiterals set; } - // TODO: document - // TODO: test + /** + * Representation of 'now' that is to be used whenever a reference is required. + * Should be used in place of System.now or DateTime.now + * + * The existance allows for the clock to be re-set in Unit Tests. + */ public static DateTime now { get @@ -49,6 +57,20 @@ public inherited sharing class ortoo_DateLiterals set; } + /** + * Representation of 'now' as an epoch time in seconds. + * + * Since this depends on 'now', can be re-set in unit tests by chaning + * the underlying 'now' + */ + public static Long epochTime + { + get + { + return DateTimeUtils.convertToEpochTime( now ); + } + } + /** * Dynamic representation of the date 'tomorrow', based on the same class's representation of 'today' */ diff --git a/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_DateLiteralsTest.cls b/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_DateLiteralsTest.cls index 8572ccac3bd..e9230d17293 100644 --- a/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_DateLiteralsTest.cls +++ b/framework/default/ortoo-core/default/classes/fflib-extension/tests/ortoo_DateLiteralsTest.cls @@ -1,4 +1,3 @@ - @isTest private without sharing class ortoo_DateLiteralsTest { @@ -9,6 +8,56 @@ private without sharing class ortoo_DateLiteralsTest System.assertEquals( Date.today(), got, 'today is set to today' ); } + @isTest + private static void today_whenSet_returnsThatDate() // NOPMD: Test method name format + { + Date expected = Date.newInstance( 2020, 5, 1 ); + ortoo_DateLiterals.today = expected; + + Date got = ortoo_DateLiterals.today; + System.assertEquals( expected, got, 'today, when set, will then be set to that value' ); + } + + @isTest + private static void now_returnsTheTimeForNow() // NOPMD: Test method name format + { + DateTime got = ortoo_DateLiterals.now; + DateTime expected = System.now(); + + System.assert( got > expected.addSeconds( -3 ) && got <= expected, 'now is set to now' ); + } + + @isTest + private static void now_whenSet_returnsThatDateTime() // NOPMD: Test method name format + { + DateTime expected = DateTime.newInstance( 2020, 5, 1, 13, 45, 0 ); + ortoo_DateLiterals.now = expected; + + DateTime got = ortoo_DateLiterals.now; + System.assertEquals( expected, got, 'now, when set, will then be set to that value' ); + } + + @isTest + private static void epochTime_returnsTheEpochTimeForNow() // NOPMD: Test method name format + { + Long expected = DateTimeUtils.convertToEpochTime( System.now() ); + + Long got = ortoo_DateLiterals.epochTime; + System.assert( got > expected - 3 && got <= expected, 'epochTime is set to now in seconds' ); + } + + @isTest + private static void epochTime_whenNowSet_returnsTheEpochForThatTime() // NOPMD: Test method name format + { + DateTime expectedDateTime = DateTime.newInstanceGmt( 2020, 5, 1, 13, 45, 0 ); + Long expectedEpoch = 1588340700; + + ortoo_DateLiterals.now = expectedDateTime; + + Long got = ortoo_DateLiterals.epochTime; + System.assertEquals( expectedEpoch, got, 'epochTime, when now is set, will then be set to the epoch for that value' ); + } + @isTest private static void yesterday_returnYesterdayBasedOnTheConfiguredToday() // NOPMD: Test method name format { diff --git a/framework/default/ortoo-core/default/classes/test-utils/TestDateTimeUtils.cls b/framework/default/ortoo-core/default/classes/test-utils/TestDateTimeUtils.cls index 9b0e1d86c92..38c1490af4b 100644 --- a/framework/default/ortoo-core/default/classes/test-utils/TestDateTimeUtils.cls +++ b/framework/default/ortoo-core/default/classes/test-utils/TestDateTimeUtils.cls @@ -23,6 +23,6 @@ public inherited sharing class TestDateTimeUtils public static void addToCurrentTime( Integer numberOfSeconds ) { - ortoo_DateLiterals.now = DateTimeUtils.convertToDateTime( DateTimeUtils.getEpochTime( ortoo_DateLiterals.now ) + numberOfSeconds ); + ortoo_DateLiterals.now = DateTimeUtils.convertToDateTime( ortoo_DateLiterals.epochTime + numberOfSeconds ); } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/utils/DateTimeUtils.cls b/framework/default/ortoo-core/default/classes/utils/DateTimeUtils.cls index c6956e70d18..f74471fa45f 100644 --- a/framework/default/ortoo-core/default/classes/utils/DateTimeUtils.cls +++ b/framework/default/ortoo-core/default/classes/utils/DateTimeUtils.cls @@ -6,28 +6,29 @@ public inherited sharing class DateTimeUtils { /** - * Returns the current Epoch Time, in seconds + * Given a date time, will convert it into the epoch time, in seconds * - * @return Long The current Epoch Time, in seconds + * @param DateTime The time to convert + * @return Long The epoch time, in number of seconds */ - // TODO: should this be on DateLiterals? - public static Long getEpochTime() + public static Long convertToEpochTime( DateTime timeToConvert ) { - return getEpochTime( ortoo_DateLiterals.now ); - } + Contract.requires( timeToConvert != null, 'convertToEpochTime called with a null timeToConvert' ); - // TODO: test - // TODO: document - public static Long getEpochTime( DateTime timeToConvert ) - { Long milliseconds = timeToConvert.getTime(); return milliseconds / 1000; } - // TODO: test - // TODO: document + /** + * Given an epoch time in seconds, will convert it into a DateTime + * + * @return Long The epoch time, in number of seconds + * @param DateTime The resulting DateTime + */ public static DateTime convertToDateTime( Long epochInSeconds ) { + Contract.requires( epochInSeconds != null, 'convertToDateTime called with a null epochInSeconds' ); + return DateTime.newInstance( epochInSeconds * 1000 ); } } diff --git a/framework/default/ortoo-core/default/classes/utils/tests/DateTimeUtilsTest.cls b/framework/default/ortoo-core/default/classes/utils/tests/DateTimeUtilsTest.cls index c947793b716..c41fd41621c 100644 --- a/framework/default/ortoo-core/default/classes/utils/tests/DateTimeUtilsTest.cls +++ b/framework/default/ortoo-core/default/classes/utils/tests/DateTimeUtilsTest.cls @@ -1,18 +1,65 @@ @isTest public with sharing class DateTimeUtilsTest { - @isTest - private static void getEpochTime_whenCalled_returnsEpochInSeconds() // NOPMD: Test method name format - { - Test.startTest(); - Long got = DateTimeUtils.getEpochTime(); - Test.stopTest(); - - Integer e9 = Integer.valueOf( got / 1000000000 ); // if you divide the epoch seconds by 10^9, you should get 1 if the date is later than 9th September 2001 - Integer e10 = Integer.valueOf( ( got / 1000000000 ) / 10 ); // if you divide the epoch seconds by 10^10, you should get < 1 if the date is earlier than 20th November 2286 - // need to do it in two steps becayse 10^10 is not a valid integer - - System.assert( e9 > 0, 'getEpochTime, when called, will return the epoch time in seconds - being greater than 10^9' ); - System.assertEquals( 0, e10, 'getEpochTime, when called, will return the epoch time in seconds - being less than 10^10' ); - } -} + @isTest + private static void convertToEpochTime_whenGivenADateTime_convertsItToEpochInSeconds() // NOPMD: Test method name format + { + DateTime timeToConvert = DateTime.newInstanceGmt( 2020, 5, 1, 13, 45, 0 ); + Long expected = 1588340700; + + Test.startTest(); + Long got = DateTimeUtils.convertToEpochTime( timeToConvert ); + Test.stopTest(); + + System.assertEquals( expected, got, 'convertToEpochTime, when given a date time, will convert it to epoch in seconds' ); + } + + @isTest + private static void convertToEpochTime_whenPassedANullTimeToConvert_throwsAnException() // NOPMD: Test method name format + { + Test.startTest(); + String exceptionMessage; + try + { + DateTimeUtils.convertToEpochTime( null ); + } + catch ( Contract.RequiresException e ) + { + exceptionMessage = e.getMessage(); + } + Test.stopTest(); + + ortoo_Asserts.assertContains( 'convertToEpochTime called with a null timeToConvert', exceptionMessage, 'convertToEpochTime, when passed a null timeToConvert, will throw an exception' ); + } + + @isTest + private static void convertToDateTime_whenGivenAEpochInSeconds_convertsItToDateTime() // NOPMD: Test method name format + { + Long epochInSeconds = 1588340700; + DateTime expected = DateTime.newInstanceGmt( 2020, 5, 1, 13, 45, 0 ); + + Test.startTest(); + DateTime got = DateTimeUtils.convertToDateTime( epochInSeconds ); + Test.stopTest(); + + System.assertEquals( expected, got, 'convertToDateTime, when given an epoch time in seconds, will convert it to DateTime' ); + } + + @isTest + private static void convertToDateTime_whenPassedANullEpochInSeconds_throwsAnException() // NOPMD: Test method name format + { + Test.startTest(); + String exceptionMessage; + try + { + DateTimeUtils.convertToDateTime( null ); + } + catch ( Contract.RequiresException e ) + { + exceptionMessage = e.getMessage(); + } + Test.stopTest(); + + ortoo_Asserts.assertContains( 'convertToDateTime called with a null epochInSeconds', exceptionMessage, 'convertToDateTime, when passed a null epochInSeconds, will throw an exception' ); + } +} \ No newline at end of file diff --git a/framework/default/ortoo-lwc-list-view-buttons/classes/AbstractRedirectToLwcTabController.cls b/framework/default/ortoo-lwc-list-view-buttons/classes/AbstractRedirectToLwcTabController.cls index 274ab7a9cca..a714b72aa24 100644 --- a/framework/default/ortoo-lwc-list-view-buttons/classes/AbstractRedirectToLwcTabController.cls +++ b/framework/default/ortoo-lwc-list-view-buttons/classes/AbstractRedirectToLwcTabController.cls @@ -64,7 +64,7 @@ public virtual with sharing class AbstractRedirectToLwcTabController { get { - return String.valueOf( DateTimeUtils.getEpochTime() ); + return String.valueOf( ortoo_DateLiterals.epochTime ); } } diff --git a/framework/default/ortoo-lwc-list-view-buttons/classes/TimeController.cls b/framework/default/ortoo-lwc-list-view-buttons/classes/TimeController.cls index 4f57bd26fbd..5512842e7cf 100644 --- a/framework/default/ortoo-lwc-list-view-buttons/classes/TimeController.cls +++ b/framework/default/ortoo-lwc-list-view-buttons/classes/TimeController.cls @@ -12,6 +12,6 @@ public with sharing class TimeController @AuraEnabled public static Long getEpochTime() { - return DateTimeUtils.getEpochTime(); + return ortoo_DateLiterals.epochTime; } } \ No newline at end of file