Skip to content

Commit

Permalink
Merge branch 'feature/filter-and-paging-backend' into feature/filter-…
Browse files Browse the repository at this point in the history
…and-paging
  • Loading branch information
rob-baillie-ortoo committed Jan 25, 2022
2 parents df408a0 + f71596b commit 89bffc0
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,34 @@
*/
public inherited sharing class SearchResults
{
@AuraEnabled public Integer totalNumberOfRecords;
@AuraEnabled public List<Object> records;
@AuraEnabled public Integer totalNumberOfRecords;
@AuraEnabled public List<Object> records;

/**
/**
* Constructor, defining the dataset
*
* @param Integer The total nmumber of records of which these records are a subset
* @param List<Object> The subset of records
* @param List<Object> The subset of records
*/
public SearchResults( Integer totalNumberOfRecords, List<Object> records )
{
Contract.requires( totalNumberOfRecords != null, 'constructor called with a null totalNumberOfRecords' );
Contract.requires( totalNumberOfRecords >= 0, 'constructor called with a negative totalNumberOfRecords' );
Contract.requires( records != null, 'constructor called with a null records' );
public SearchResults( Integer totalNumberOfRecords, List<Object> records )
{
Contract.requires( totalNumberOfRecords != null, 'constructor called with a null totalNumberOfRecords' );
Contract.requires( totalNumberOfRecords >= 0, 'constructor called with a negative totalNumberOfRecords' );
Contract.requires( records != null, 'constructor called with a null records' );

Contract.requires( totalNumberOfRecords >= records.size(), 'constructor called with a totalNumberOfRecords that is lower than the size of records' );
Contract.requires( totalNumberOfRecords >= records.size(), 'constructor called with a totalNumberOfRecords that is lower than the size of records' );

this.totalNumberOfRecords = totalNumberOfRecords;
this.records = records;
}
this.totalNumberOfRecords = totalNumberOfRecords;
this.records = records;
}

/**
* States if there are currently records in this result set
*
* @return Boolean States if there are currently records in this result set
*/
public Boolean hasRecords()
{
return !records.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,24 @@ public inherited sharing class SearchResultsTest

Amoss_Asserts.assertContains( 'constructor called with a totalNumberOfRecords that is lower than the size of records', exceptionMessage, 'constructor, when passed a total number of records that is lower than the number of records, will throw an exception' );
}

@isTest
private static void hasRecords_whenResultsHaveBeenSetToAnEmptyList_returnsFalse() // NOPMD: Test method name format
{
Test.startTest();
Boolean got = new SearchResults( 15, new List<Object>() ).hasRecords();
Test.stopTest();

System.assertEquals( false, got, 'hasRecords, when results have been set to an empty list, will return false' );
}

@isTest
private static void hasRecords_whenResultsHaveBeenSetWithRecords_returnsTrue() // NOPMD: Test method name format
{
Test.startTest();
Boolean got = new SearchResults( 15, new List<Object>{ 1, 2 } ).hasRecords();
Test.stopTest();

System.assertEquals( true, got, 'hasRecords, when results have been set to a list with records, will return true' );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ public with sharing class SearchServiceImpl implements ISearchService
SearchResults searchResults = ((ISearchSelector)Application.SELECTOR.newInstance( sObjectType ) )
.selectBySearchCriteria( searchConfiguration, criteria, window, orderBy );

ISearchResultBuilder searchResultsBuilder = ((ISearchResultBuilder)Application.DOMAIN.newInstance( (List<Sobject>)searchResults.records ) );

searchResults.records = searchResultsBuilder.buildSearchResults( searchConfiguration );
if ( searchResults.hasRecords() )
{
ISearchResultBuilder searchResultsBuilder = ((ISearchResultBuilder)Application.DOMAIN.newInstance( (List<Sobject>)searchResults.records ) );
searchResults.records = searchResultsBuilder.buildSearchResults( searchConfiguration );
}

Contract.ensures( searchResults != null, 'search attempted to return with a null searchResults' );
Contract.ensures( searchResults.records != null, 'search attempted to return with a null searchResults.records' );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ public inherited sharing class SearchServiceImplTest
Amoss_Instance selectorController = ApplicationMockRegistrar.registerMockSelector( searchSobjectType, SearchServiceMockSearchSelector.class ); // the config will say this is the SobjectType we're searching for
Amoss_Instance domainController = ApplicationMockRegistrar.registerMockDomain( searchSobjectType, SearchServiceMockDomain.class );

SearchResults interimSearchResults = new SearchResults( 1, new List<Contact>{ new Contact( FirstName = 'Interim') } );
// it looks like it shouldn't, but selectBySearchCriteria does appear to return a list based on the actual SObject type, if there are records
// Therefore we return a SearchResults built with List<Contact>, and not List<Sobject>, as you might expect.
SearchResults interimSearchResults = new SearchResults( 1, new List<Contact>{ new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ), FirstName = 'Interim') } );
List<ISearchResult> adjustedObjects = new List<ISearchResult>{ finalResult };

// configure the expected behaviours
Expand Down Expand Up @@ -53,6 +55,46 @@ public inherited sharing class SearchServiceImplTest
System.assertEquals( adjustedObjects, results.records, 'search, when called with a config, criteria, window and order by, will construct a domain object based on the cofig, with the results from the selector and then ask it to buildSearchResults from them' );
}

@isTest
private static void search_whenNoRecordsAreReturnedByTheSearch_doesNotTryToCreateTheDomain() // NOPMD: Test method name format
{
SobjectType searchSobjectType = Contact.sobjectType;
Type searchConfigurationType = ISearchConfiguration.class;

// Define all the mocks and register them where appropriate
ISearchCriteria criteria = (ISearchCriteria)new Amoss_Instance( ISearchCriteria.class ).generateDouble();
SearchWindow window = (SearchWindow)new Amoss_Instance( SearchWindow.class ).generateDouble();
SearchOrderBy orderBy = (SearchOrderBy)new Amoss_Instance( SearchOrderBy.class ).generateDouble();

ISearchResult finalResult = (ISearchResult)new Amoss_Instance( ISearchResult.class ).generateDouble();

Amoss_Instance searchConfigController = ApplicationMockRegistrar.registerMockAppLogic( searchConfigurationType );
Amoss_Instance selectorController = ApplicationMockRegistrar.registerMockSelector( searchSobjectType, SearchServiceMockSearchSelector.class ); // the config will say this is the SobjectType we're searching for

SearchResults interimSearchResults = new SearchResults( 0, new List<Sobject>() );

// configure the expected behaviours
searchConfigController
.expects( 'getBaseSobjectType' )
.returns( searchSobjectType );

selectorController
.when( 'selectBySearchCriteria' )
.returns( interimSearchResults );

Test.startTest();

SearchResults results = new SearchServiceImpl().search( searchConfigurationType, criteria, window, orderBy );

Test.stopTest();

searchConfigController.verify();
selectorController.verify();

System.assertEquals( 0, results.totalNumberOfRecords, 'search, when the search matches no records, will give a total number of records of zero' );
System.assertEquals( 0, results.records.size(), 'search, when the search matches no records, will return an empty search results' );
}

@isTest
private static void search_whenPassedANullSearchConfigurationType_throwsAnException() // NOPMD: Test method name format
{
Expand Down

0 comments on commit 89bffc0

Please sign in to comment.