From 55cba1e0f3373fa69d3b9a66f455ad36ab4b82cf Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sun, 20 Mar 2016 17:07:26 -0700 Subject: Adding support for Church Community Builder login. Beginning with this change all of the Church Management System integration logic is moving into implementations of the new IntegrationDriver interface. The desired IntegrationDriver can be selected by setting the integrationDriver config to the appropriate class name. This commit is only moving login support. Progress reporting will move in a later commit. --- tst/com/p4square/grow/ccb/CCBUserVerifierTest.java | 139 +++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 tst/com/p4square/grow/ccb/CCBUserVerifierTest.java (limited to 'tst') diff --git a/tst/com/p4square/grow/ccb/CCBUserVerifierTest.java b/tst/com/p4square/grow/ccb/CCBUserVerifierTest.java new file mode 100644 index 0000000..d17b698 --- /dev/null +++ b/tst/com/p4square/grow/ccb/CCBUserVerifierTest.java @@ -0,0 +1,139 @@ +package com.p4square.grow.ccb; + +import com.p4square.ccbapi.CCBAPI; +import com.p4square.ccbapi.model.GetIndividualProfilesRequest; +import com.p4square.ccbapi.model.GetIndividualProfilesResponse; +import com.p4square.ccbapi.model.IndividualProfile; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.data.ChallengeResponse; +import org.restlet.data.ChallengeScheme; +import org.restlet.data.ClientInfo; +import org.restlet.security.Verifier; + +import java.io.IOException; +import java.util.Collections; + +import static org.junit.Assert.*; + +/** + * Tests for CCBUserVerifier. + */ +public class CCBUserVerifierTest { + + private IndividualProfile mProfile = new IndividualProfile(); + + private CCBAPI mAPI; + private CCBUserVerifier verifier; + + private ClientInfo mClientInfo; + private Request mMockRequest; + private Response mMockResponse; + + @Before + public void setUp() { + mAPI = EasyMock.mock(CCBAPI.class); + verifier = new CCBUserVerifier(mAPI); + + mClientInfo = new ClientInfo(); + mMockRequest = EasyMock.mock(Request.class); + EasyMock.expect(mMockRequest.getClientInfo()).andReturn(mClientInfo).anyTimes(); + + mMockResponse = EasyMock.mock(Response.class); + + mProfile.setId(48); + mProfile.setFirstName("Larry"); + mProfile.setLastName("Bob"); + mProfile.setEmail("larry.bob@example.com"); + } + + private void replay() { + EasyMock.replay(mAPI, mMockRequest, mMockResponse); + } + + private void verify() { + EasyMock.verify(mAPI, mMockRequest, mMockResponse); + } + + + @Test + public void testVerifyNoCredentials() throws Exception { + // Prepare mocks + EasyMock.expect(mMockRequest.getChallengeResponse()).andReturn(null).anyTimes(); + replay(); + + // Test + int result = verifier.verify(mMockRequest, mMockResponse); + + // Verify + verify(); + assertEquals(Verifier.RESULT_MISSING, result); + assertNull(mClientInfo.getUser()); + } + + @Test + public void testVerifyAuthFailure() throws Exception { + // Prepare mocks + ChallengeResponse challenge = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, "user", "pass"); + EasyMock.expect(mMockRequest.getChallengeResponse()).andReturn(challenge).anyTimes(); + GetIndividualProfilesResponse response = new GetIndividualProfilesResponse(); + response.setIndividuals(Collections.emptyList()); + EasyMock.expect(mAPI.getIndividualProfiles(new GetIndividualProfilesRequest() + .withLoginPassword("user", "pass".toCharArray()))).andReturn(response); + replay(); + + // Test + int result = verifier.verify(mMockRequest, mMockResponse); + + // Verify + verify(); + assertEquals(Verifier.RESULT_INVALID, result); + assertNull(mClientInfo.getUser()); + } + + @Test + public void testVerifyAuthException() throws Exception { + // Prepare mocks + ChallengeResponse challenge = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, "user", "pass"); + EasyMock.expect(mMockRequest.getChallengeResponse()).andReturn(challenge).anyTimes(); + EasyMock.expect(mAPI.getIndividualProfiles(EasyMock.anyObject(GetIndividualProfilesRequest.class))) + .andThrow(new IOException()); + replay(); + + // Test + int result = verifier.verify(mMockRequest, mMockResponse); + + // Verify + verify(); + assertEquals(Verifier.RESULT_INVALID, result); + assertNull(mClientInfo.getUser()); + } + + @Test + public void testVerifyAuthSuccess() throws Exception { + // Prepare mocks + ChallengeResponse challenge = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, "user", "pass"); + EasyMock.expect(mMockRequest.getChallengeResponse()).andReturn(challenge).anyTimes(); + GetIndividualProfilesResponse response = new GetIndividualProfilesResponse(); + response.setIndividuals(Collections.singletonList(mProfile)); + EasyMock.expect(mAPI.getIndividualProfiles(new GetIndividualProfilesRequest() + .withLoginPassword("user", "pass".toCharArray()))).andReturn(response); + + replay(); + + // Test + int result = verifier.verify(mMockRequest, mMockResponse); + + // Verify + verify(); + assertEquals(Verifier.RESULT_VALID, result); + assertNotNull(mClientInfo.getUser()); + assertEquals("CCB-48", mClientInfo.getUser().getIdentifier()); + assertEquals("Larry", mClientInfo.getUser().getFirstName()); + assertEquals("Bob", mClientInfo.getUser().getLastName()); + assertEquals("larry.bob@example.com", mClientInfo.getUser().getEmail()); + } +} \ No newline at end of file -- cgit v1.2.3 From 918e806c83f812721f0e9527fbc3e3e67d071580 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Thu, 7 Apr 2016 21:25:12 -0700 Subject: Adding CustomFieldCache for CCB User Defined Fields. --- src/com/p4square/grow/ccb/CustomFieldCache.java | 126 ++++++++++++ .../p4square/grow/ccb/CustomFieldCacheTest.java | 221 +++++++++++++++++++++ 2 files changed, 347 insertions(+) create mode 100644 src/com/p4square/grow/ccb/CustomFieldCache.java create mode 100644 tst/com/p4square/grow/ccb/CustomFieldCacheTest.java (limited to 'tst') diff --git a/src/com/p4square/grow/ccb/CustomFieldCache.java b/src/com/p4square/grow/ccb/CustomFieldCache.java new file mode 100644 index 0000000..ba473fb --- /dev/null +++ b/src/com/p4square/grow/ccb/CustomFieldCache.java @@ -0,0 +1,126 @@ +package com.p4square.grow.ccb; + +import com.p4square.ccbapi.CCBAPI; +import com.p4square.ccbapi.model.*; +import org.apache.log4j.Logger; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * CustomFieldCache maintains an index from custom field labels to names. + */ +public class CustomFieldCache { + + private static final Logger LOG = Logger.getLogger(CustomFieldCache.class); + + private final CCBAPI mAPI; + + private CustomFieldCollection mTextFields; + private CustomFieldCollection mDateFields; + private CustomFieldCollection mIndividualPulldownFields; + private CustomFieldCollection mGroupPulldownFields; + + private final Map> mItemByNameTable; + + public CustomFieldCache(final CCBAPI api) { + mAPI = api; + mTextFields = new CustomFieldCollection<>(); + mDateFields = new CustomFieldCollection<>(); + mIndividualPulldownFields = new CustomFieldCollection<>(); + mGroupPulldownFields = new CustomFieldCollection<>(); + mItemByNameTable = new HashMap<>(); + } + + public CustomField getTextFieldByLabel(final String label) { + if (mTextFields.size() == 0) { + refresh(); + } + return mTextFields.getByLabel(label); + } + + public CustomField getDateFieldByLabel(final String label) { + if (mDateFields.size() == 0) { + refresh(); + } + return mDateFields.getByLabel(label); + } + + public CustomField getIndividualPulldownByLabel(final String label) { + if (mIndividualPulldownFields.size() == 0) { + refresh(); + } + return mIndividualPulldownFields.getByLabel(label); + } + + public CustomField getGroupPulldownByLabel(final String label) { + if (mGroupPulldownFields.size() == 0) { + refresh(); + } + return mGroupPulldownFields.getByLabel(label); + } + + public LookupTableItem getPulldownItemByName(final LookupTableType type, final String name) { + Map items = mItemByNameTable.get(type); + if (items == null) { + if (!cacheLookupTable(type)) { + return null; + } + items = mItemByNameTable.get(type); + } + + return items.get(name); + } + + private synchronized void refresh() { + try { + // Get all of the custom fields. + final GetCustomFieldLabelsResponse resp = mAPI.getCustomFieldLabels(); + + final CustomFieldCollection newTextFields = new CustomFieldCollection<>(); + final CustomFieldCollection newDateFields = new CustomFieldCollection<>(); + final CustomFieldCollection newIndPulldownFields = new CustomFieldCollection<>(); + final CustomFieldCollection newGrpPulldownFields = new CustomFieldCollection<>(); + + for (final CustomField field : resp.getCustomFields()) { + if (field.getName().startsWith("udf_ind_text_")) { + newTextFields.add(field); + } else if (field.getName().startsWith("udf_ind_date_")) { + newDateFields.add(field); + } else if (field.getName().startsWith("udf_ind_pulldown_")) { + newIndPulldownFields.add(field); + } else if (field.getName().startsWith("udf_grp_pulldown_")) { + newGrpPulldownFields.add(field); + } else { + LOG.warn("Unknown custom field type " + field.getName()); + } + } + + this.mTextFields = newTextFields; + this.mDateFields = newDateFields; + this.mIndividualPulldownFields = newIndPulldownFields; + this.mGroupPulldownFields = newGrpPulldownFields; + + } catch (IOException e) { + // Error fetching labels. + LOG.error("Error fetching custom fields: " + e.getMessage(), e); + } + } + + private synchronized boolean cacheLookupTable(final LookupTableType type) { + try { + final GetLookupTableResponse resp = mAPI.getLookupTable(new GetLookupTableRequest().withType(type)); + mItemByNameTable.put(type, + resp.getItems().stream().collect(Collectors.toMap(LookupTableItem::getName, Function.identity()))); + return true; + + } catch (IOException e) { + LOG.error("Exception caching lookup table of type " + type, e); + } + + return false; + } +} diff --git a/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java b/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java new file mode 100644 index 0000000..e374496 --- /dev/null +++ b/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java @@ -0,0 +1,221 @@ +package com.p4square.grow.ccb; + +import com.p4square.ccbapi.CCBAPI; +import com.p4square.ccbapi.model.*; +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; + +import static org.junit.Assert.*; + +/** + * Tests for the CustomFieldCache. + */ +public class CustomFieldCacheTest { + + private CustomFieldCache cache; + + private CCBAPI api; + private GetCustomFieldLabelsResponse customFieldsResponse; + private GetLookupTableResponse lookupTableResponse; + + @Before + public void setUp() { + api = EasyMock.mock(CCBAPI.class); + cache = new CustomFieldCache(api); + + // Prepare some custom fields for the test. + CustomField textField = new CustomField(); + textField.setName("udf_ind_text_6"); + textField.setLabel("Grow Level"); + + CustomField dateField = new CustomField(); + dateField.setName("udf_ind_date_6"); + dateField.setLabel("Grow Level"); + + CustomField pullDown = new CustomField(); + pullDown.setName("udf_ind_pulldown_6"); + pullDown.setLabel("Grow Level"); + + customFieldsResponse = new GetCustomFieldLabelsResponse(); + customFieldsResponse.setCustomFields(Arrays.asList(textField, dateField, pullDown)); + + // Prepare some pulldown items for the tests. + LookupTableItem seeker = new LookupTableItem(); + seeker.setId(1); + seeker.setOrder(1); + seeker.setName("Seeker"); + + LookupTableItem believer = new LookupTableItem(); + believer.setId(2); + believer.setOrder(2); + believer.setName("Believer"); + + lookupTableResponse = new GetLookupTableResponse(); + lookupTableResponse.setItems(Arrays.asList(seeker, believer)); + } + + @Test + public void testGetTextFieldByLabel() throws Exception { + // Setup mocks + EasyMock.expect(api.getCustomFieldLabels()).andReturn(customFieldsResponse); + EasyMock.replay(api); + + // Test the cache + CustomField field = cache.getTextFieldByLabel("Grow Level"); + + // Verify result. + EasyMock.verify(api); + assertEquals("udf_ind_text_6", field.getName()); + assertEquals("Grow Level", field.getLabel()); + } + + @Test + public void testGetDateFieldByLabel() throws Exception { + // Setup mocks + EasyMock.expect(api.getCustomFieldLabels()).andReturn(customFieldsResponse); + EasyMock.replay(api); + + // Test the cache + CustomField field = cache.getDateFieldByLabel("Grow Level"); + + // Verify result. + EasyMock.verify(api); + assertEquals("udf_ind_date_6", field.getName()); + assertEquals("Grow Level", field.getLabel()); + } + + @Test + public void testGetPullDownFieldByLabel() throws Exception { + // Setup mocks + EasyMock.expect(api.getCustomFieldLabels()).andReturn(customFieldsResponse); + EasyMock.replay(api); + + // Test the cache + CustomField field = cache.getIndividualPulldownByLabel("Grow Level"); + + // Verify result. + EasyMock.verify(api); + assertEquals("udf_ind_pulldown_6", field.getName()); + assertEquals("Grow Level", field.getLabel()); + } + + @Test + public void testGetPullDownFieldByLabelMissing() throws Exception { + // Setup mocks + EasyMock.expect(api.getCustomFieldLabels()).andReturn(customFieldsResponse); + EasyMock.replay(api); + + // Test the cache + CustomField field = cache.getIndividualPulldownByLabel("Missing Label"); + + // Verify result. + EasyMock.verify(api); + assertNull(field); + } + + @Test + public void testGetPullDownFieldByLabelException() throws Exception { + // Setup mocks + EasyMock.expect(api.getCustomFieldLabels()).andThrow(new IOException()); + EasyMock.expect(api.getCustomFieldLabels()).andReturn(customFieldsResponse); + EasyMock.replay(api); + + // Test the cache + CustomField field1 = cache.getIndividualPulldownByLabel("Grow Level"); + CustomField field2 = cache.getIndividualPulldownByLabel("Grow Level"); + + // Verify result. + EasyMock.verify(api); + assertNull(field1); + assertNotNull(field2); + } + + @Test + public void testGetMultipleFields() throws Exception { + // Setup mocks + // Note: only one API call. + EasyMock.expect(api.getCustomFieldLabels()).andReturn(customFieldsResponse); + EasyMock.replay(api); + + // Test the cache + CustomField field1 = cache.getTextFieldByLabel("Grow Level"); + CustomField field2 = cache.getIndividualPulldownByLabel("Grow Level"); + + // Verify result. + EasyMock.verify(api); + assertEquals("udf_ind_text_6", field1.getName()); + assertEquals("Grow Level", field1.getLabel()); + assertEquals("udf_ind_pulldown_6", field2.getName()); + assertEquals("Grow Level", field2.getLabel()); + } + + @Test + public void testGetPullDownOptions() throws Exception { + // Setup mocks + Capture requestCapture = EasyMock.newCapture(); + EasyMock.expect(api.getLookupTable(EasyMock.capture(requestCapture))).andReturn(lookupTableResponse); + EasyMock.replay(api); + + // Test the cache + LookupTableItem item = cache.getPulldownItemByName( + LookupTableType.valueOf("udf_ind_pulldown_6".toUpperCase()), + "Believer"); + + // Verify result. + EasyMock.verify(api); + assertEquals(LookupTableType.UDF_IND_PULLDOWN_6, requestCapture.getValue().getType()); + assertEquals(2, item.getId()); + assertEquals(2, item.getOrder()); + assertEquals("Believer", item.getName()); + } + + @Test + public void testGetPullDownOptionMissing() throws Exception { + // Setup mocks + EasyMock.expect(api.getLookupTable(EasyMock.anyObject())).andReturn(lookupTableResponse); + EasyMock.replay(api); + + // Test the cache + LookupTableItem item = cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_6, "Something else"); + + // Verify result. + EasyMock.verify(api); + assertNull(item); + } + + @Test + public void testGetPullDownMissing() throws Exception { + // Setup mocks + EasyMock.expect(api.getLookupTable(EasyMock.anyObject())).andReturn(new GetLookupTableResponse()); + EasyMock.replay(api); + + // Test the cache + LookupTableItem item = cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_6, "Believer"); + + // Verify result. + EasyMock.verify(api); + assertNull(item); + } + + @Test + public void testGetPullDownException() throws Exception { + // Setup mocks + EasyMock.expect(api.getLookupTable(EasyMock.anyObject())).andThrow(new IOException()); + EasyMock.expect(api.getLookupTable(EasyMock.anyObject())).andReturn(lookupTableResponse); + EasyMock.replay(api); + + // Test the cache + LookupTableItem item1 = cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_6, "Believer"); + LookupTableItem item2 = cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_6, "Believer"); + + // Verify result. + EasyMock.verify(api); + assertNull(item1); + assertNotNull(item2); + } +} \ No newline at end of file -- cgit v1.2.3 From 10c5fd17b603f125ae2c0ef14b1a65341dbdf961 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sat, 9 Apr 2016 09:48:56 -0700 Subject: CustomFieldCache is now case-insensitive. --- src/com/p4square/grow/ccb/CustomFieldCache.java | 6 +++--- tst/com/p4square/grow/ccb/CustomFieldCacheTest.java | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'tst') diff --git a/src/com/p4square/grow/ccb/CustomFieldCache.java b/src/com/p4square/grow/ccb/CustomFieldCache.java index ba473fb..d93e6d9 100644 --- a/src/com/p4square/grow/ccb/CustomFieldCache.java +++ b/src/com/p4square/grow/ccb/CustomFieldCache.java @@ -72,7 +72,7 @@ public class CustomFieldCache { items = mItemByNameTable.get(type); } - return items.get(name); + return items.get(name.toLowerCase()); } private synchronized void refresh() { @@ -113,8 +113,8 @@ public class CustomFieldCache { private synchronized boolean cacheLookupTable(final LookupTableType type) { try { final GetLookupTableResponse resp = mAPI.getLookupTable(new GetLookupTableRequest().withType(type)); - mItemByNameTable.put(type, - resp.getItems().stream().collect(Collectors.toMap(LookupTableItem::getName, Function.identity()))); + mItemByNameTable.put(type, resp.getItems().stream().collect( + Collectors.toMap(item -> item.getName().toLowerCase(), Function.identity()))); return true; } catch (IOException e) { diff --git a/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java b/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java index e374496..bcfd260 100644 --- a/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java +++ b/tst/com/p4square/grow/ccb/CustomFieldCacheTest.java @@ -174,6 +174,26 @@ public class CustomFieldCacheTest { assertEquals("Believer", item.getName()); } + @Test + public void testGetPullDownOptionsMixedCase() throws Exception { + // Setup mocks + Capture requestCapture = EasyMock.newCapture(); + EasyMock.expect(api.getLookupTable(EasyMock.capture(requestCapture))).andReturn(lookupTableResponse); + EasyMock.replay(api); + + // Test the cache + LookupTableItem item = cache.getPulldownItemByName( + LookupTableType.valueOf("udf_ind_pulldown_6".toUpperCase()), + "BeLiEvEr"); + + // Verify result. + EasyMock.verify(api); + assertEquals(LookupTableType.UDF_IND_PULLDOWN_6, requestCapture.getValue().getType()); + assertEquals(2, item.getId()); + assertEquals(2, item.getOrder()); + assertEquals("Believer", item.getName()); + } + @Test public void testGetPullDownOptionMissing() throws Exception { // Setup mocks -- cgit v1.2.3 From 9d7cd517e8a00049357ce6ec4b65cb5a12dc2f24 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sat, 9 Apr 2016 09:51:01 -0700 Subject: Implementing CCBProgressReporter This reporter updates two pairs of user-defined fields on an Individual Profile. The first pair are pulldown & date fields used to track the assessment results. The second pair are updated after each chapter is completed. --- src/com/p4square/grow/ccb/CCBProgressReporter.java | 82 ++++++- .../ChurchCommunityBuilderIntegrationDriver.java | 3 +- src/com/p4square/grow/model/Score.java | 2 + .../p4square/grow/ccb/CCBProgressReporterTest.java | 235 +++++++++++++++++++++ 4 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 tst/com/p4square/grow/ccb/CCBProgressReporterTest.java (limited to 'tst') diff --git a/src/com/p4square/grow/ccb/CCBProgressReporter.java b/src/com/p4square/grow/ccb/CCBProgressReporter.java index e2304fe..d2826eb 100644 --- a/src/com/p4square/grow/ccb/CCBProgressReporter.java +++ b/src/com/p4square/grow/ccb/CCBProgressReporter.java @@ -1,9 +1,15 @@ package com.p4square.grow.ccb; import com.p4square.ccbapi.CCBAPI; +import com.p4square.ccbapi.model.*; import com.p4square.grow.frontend.ProgressReporter; +import com.p4square.grow.model.Score; +import org.apache.log4j.Logger; import org.restlet.security.User; +import java.io.IOException; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.Date; /** @@ -14,19 +20,85 @@ import java.util.Date; */ public class CCBProgressReporter implements ProgressReporter { + private static final Logger LOG = Logger.getLogger(CCBProgressReporter.class); + + private static final String GROW_LEVEL = "GrowLevelTrain"; + private static final String GROW_ASSESSMENT = "GrowLevelAsmnt"; + private final CCBAPI mAPI; + private final CustomFieldCache mCache; - public CCBProgressReporter(final CCBAPI api) { + public CCBProgressReporter(final CCBAPI api, final CustomFieldCache cache) { mAPI = api; + mCache = cache; } @Override - public void reportAssessmentComplete(User user, String level, Date date, String results) { - // TODO + public void reportAssessmentComplete(final User user, final String level, final Date date, final String results) { + if (!(user instanceof CCBUser)) { + throw new IllegalArgumentException("Expected CCBUser but got " + user.getClass().getCanonicalName()); + } + final CCBUser ccbuser = (CCBUser) user; + + updateLevelAndDate(ccbuser, GROW_ASSESSMENT, level, date); } @Override - public void reportChapterComplete(User user, String chapter, Date date) { - // TODO + public void reportChapterComplete(final User user, final String chapter, final Date date) { + if (!(user instanceof CCBUser)) { + throw new IllegalArgumentException("Expected CCBUser but got " + user.getClass().getCanonicalName()); + } + final CCBUser ccbuser = (CCBUser) user; + + // Only update the level if it is increasing. + final CustomPulldownFieldValue currentLevel = ccbuser.getProfile() + .getCustomPulldownFields().getByLabel(GROW_LEVEL); + + if (currentLevel != null) { + if (Score.numericScore(chapter) <= Score.numericScore(currentLevel.getSelection().getLabel())) { + LOG.info("Not updating level for " + user.getIdentifier() + + " because current level (" + currentLevel.getSelection().getLabel() + + ") is greater than new level (" + chapter + ")"); + return; + } + } + + updateLevelAndDate(ccbuser, GROW_LEVEL, chapter, date); + } + + private void updateLevelAndDate(final CCBUser user, final String field, final String level, final Date date) { + boolean modified = false; + + final UpdateIndividualProfileRequest req = new UpdateIndividualProfileRequest() + .withIndividualId(user.getProfile().getId()); + + final CustomField pulldownField = mCache.getIndividualPulldownByLabel(field); + if (pulldownField != null) { + final LookupTableType type = LookupTableType.valueOf(pulldownField.getName().toUpperCase()); + final LookupTableItem item = mCache.getPulldownItemByName(type, level); + if (item != null) { + req.withCustomPulldownField(pulldownField.getName(), item.getId()); + modified = true; + } + } + + final CustomField dateField = mCache.getDateFieldByLabel(field); + if (dateField != null) { + req.withCustomDateField(dateField.getName(), date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); + modified = true; + } + + try { + // Only update if a field exists. + if (modified) { + mAPI.updateIndividualProfile(req); + } + + } catch (IOException e) { + LOG.error("updateIndividual failed for " + user.getIdentifier() + + ", field " + field + + ", level " + level + + ", date " + date.toString()); + } } } diff --git a/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java b/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java index 48d143c..fc6148f 100644 --- a/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java +++ b/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java @@ -41,7 +41,8 @@ public class ChurchCommunityBuilderIntegrationDriver implements IntegrationDrive mAPI = api; - mProgressReporter = new CCBProgressReporter(mAPI); + final CustomFieldCache cache = new CustomFieldCache(mAPI); + mProgressReporter = new CCBProgressReporter(mAPI, cache); } catch (URISyntaxException e) { throw new RuntimeException(e); diff --git a/src/com/p4square/grow/model/Score.java b/src/com/p4square/grow/model/Score.java index 82f26c9..031c309 100644 --- a/src/com/p4square/grow/model/Score.java +++ b/src/com/p4square/grow/model/Score.java @@ -17,6 +17,8 @@ public class Score { * numericScore(x.toString()) <= x.getScore() */ public static double numericScore(String score) { + score = score.toLowerCase(); + if ("teacher".equals(score)) { return 3.5; } else if ("disciple".equals(score)) { diff --git a/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java b/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java new file mode 100644 index 0000000..6854f22 --- /dev/null +++ b/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java @@ -0,0 +1,235 @@ +package com.p4square.grow.ccb; + +import com.p4square.ccbapi.CCBAPI; +import com.p4square.ccbapi.model.*; +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import java.time.LocalDate; +import java.util.Date; + +import static org.junit.Assert.*; + +/** + * Tests for the CCBProgressReporter. + */ +public class CCBProgressReporterTest { + + private static final String GROW_LEVEL = "GrowLevelTrain"; + private static final String ASSESSMENT_LEVEL = "GrowLevelAsmnt"; + + private CCBProgressReporter reporter; + + private CCBAPI api; + private CustomFieldCache cache; + + private CCBUser user; + private Date date; + + @Before + public void setUp() { + // Setup some data for testing. + IndividualProfile profile = new IndividualProfile(); + profile.setId(123); + profile.setFirstName("Larry"); + profile.setLastName("Cucumber"); + profile.setEmail("larry.cucumber@example.com"); + + user = new CCBUser(profile); + date = new Date(1427889600000L); // 2015-04-01 + + // Setup the mocks. + api = EasyMock.mock(CCBAPI.class); + cache = EasyMock.mock(CustomFieldCache.class); + reporter = new CCBProgressReporter(api, cache); + } + + private void setupCacheMocks() { + // Setup the Grow Level field. + CustomField growLevelDate = new CustomField(); + growLevelDate.setName("udf_ind_date_1"); + growLevelDate.setLabel(GROW_LEVEL); + + CustomField growLevelPulldown = new CustomField(); + growLevelPulldown.setName("udf_ind_pulldown_1"); + growLevelPulldown.setLabel(GROW_LEVEL); + + LookupTableItem believer = new LookupTableItem(); + believer.setId(1); + believer.setOrder(2); + believer.setName("Believer"); + + EasyMock.expect(cache.getDateFieldByLabel(GROW_LEVEL)) + .andReturn(growLevelDate).anyTimes(); + EasyMock.expect(cache.getIndividualPulldownByLabel(GROW_LEVEL)) + .andReturn(growLevelPulldown).anyTimes(); + EasyMock.expect(cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_1, "Believer")) + .andReturn(believer).anyTimes(); + + // Setup the Grow Assessment field. + CustomField growAssessmentDate = new CustomField(); + growAssessmentDate.setName("udf_ind_date_2"); + growAssessmentDate.setLabel(ASSESSMENT_LEVEL); + + CustomField growAssessmentPulldown = new CustomField(); + growAssessmentPulldown.setName("udf_ind_pulldown_2"); + growAssessmentPulldown.setLabel(ASSESSMENT_LEVEL); + + EasyMock.expect(cache.getDateFieldByLabel(ASSESSMENT_LEVEL)) + .andReturn(growAssessmentDate).anyTimes(); + EasyMock.expect(cache.getIndividualPulldownByLabel(ASSESSMENT_LEVEL)) + .andReturn(growAssessmentPulldown).anyTimes(); + EasyMock.expect(cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_2, "Believer")) + .andReturn(believer).anyTimes(); + } + + @Test + public void reportAssessmentComplete() throws Exception { + // Setup mocks + setupCacheMocks(); + Capture reqCapture = EasyMock.newCapture(); + EasyMock.expect(api.updateIndividualProfile(EasyMock.capture(reqCapture))) + .andReturn(EasyMock.mock(UpdateIndividualProfileResponse.class)); + replay(); + + // Test reporter + reporter.reportAssessmentComplete(user, "Believer", date, "Data"); + + // Assert that the profile was updated. + verify(); + assertTrue(reqCapture.hasCaptured()); + UpdateIndividualProfileRequest req = reqCapture.getValue(); + + // Both the Grow Level and Grow Assessment fields should be updated. + assertEquals(1, req.getCustomPulldownFields().get("udf_pulldown_1").intValue()); + assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_1").toString()); + assertEquals(1, req.getCustomPulldownFields().get("udf_pulldown_2").intValue()); + assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_2").toString()); + } + + @Test + public void testReportChapterCompleteNoPreviousChapter() throws Exception { + // Setup mocks + setupCacheMocks(); + Capture reqCapture = EasyMock.newCapture(); + EasyMock.expect(api.updateIndividualProfile(EasyMock.capture(reqCapture))) + .andReturn(EasyMock.mock(UpdateIndividualProfileResponse.class)); + replay(); + + // Test reporter + reporter.reportChapterComplete(user, "Believer", date); + + // Assert that the profile was updated. + verify(); + assertTrue(reqCapture.hasCaptured()); + UpdateIndividualProfileRequest req = reqCapture.getValue(); + assertEquals(1, req.getCustomPulldownFields().get("udf_pulldown_1").intValue()); + assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_1").toString()); + } + + @Test + public void testReportChapterCompleteLowerPreviousChapter() throws Exception { + // Setup mocks + setupCacheMocks(); + Capture reqCapture = EasyMock.newCapture(); + EasyMock.expect(api.updateIndividualProfile(EasyMock.capture(reqCapture))) + .andReturn(EasyMock.mock(UpdateIndividualProfileResponse.class)); + + setUserPulldownSelection(GROW_LEVEL, "Seeker"); + + replay(); + + // Test reporter + reporter.reportChapterComplete(user, "Believer", date); + + // Assert that the profile was updated. + verify(); + assertTrue(reqCapture.hasCaptured()); + UpdateIndividualProfileRequest req = reqCapture.getValue(); + assertEquals(1, req.getCustomPulldownFields().get("udf_pulldown_1").intValue()); + assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_1").toString()); + } + + @Test + public void testReportChapterCompleteHigherPreviousChapter() throws Exception { + // Setup mocks + setupCacheMocks(); + setUserPulldownSelection(GROW_LEVEL, "Disciple"); + + replay(); + + // Test reporter + reporter.reportChapterComplete(user, "Believer", date); + + // Assert that the profile was updated. + verify(); + } + + @Test + public void testReportChapterCompleteNoCustomField() throws Exception { + // Setup mocks + EasyMock.expect(cache.getDateFieldByLabel(EasyMock.anyString())).andReturn(null).anyTimes(); + EasyMock.expect(cache.getIndividualPulldownByLabel(EasyMock.anyString())).andReturn(null).anyTimes(); + EasyMock.expect(cache.getPulldownItemByName(EasyMock.anyObject(), EasyMock.anyString())) + .andReturn(null).anyTimes(); + replay(); + + // Test reporter + reporter.reportChapterComplete(user, "Believer", date); + + // Assert that the profile was updated. + verify(); + } + + @Test + public void testReportChapterCompleteNoSuchValue() throws Exception { + // Setup mocks + setupCacheMocks(); + EasyMock.expect(cache.getPulldownItemByName(LookupTableType.UDF_IND_PULLDOWN_1, "Foo")) + .andReturn(null).anyTimes(); + Capture reqCapture = EasyMock.newCapture(); + EasyMock.expect(api.updateIndividualProfile(EasyMock.capture(reqCapture))) + .andReturn(EasyMock.mock(UpdateIndividualProfileResponse.class)); + replay(); + + // Test reporter + reporter.reportChapterComplete(user, "Foo", date); + + // Assert that the profile was updated. + verify(); + assertTrue(reqCapture.hasCaptured()); + UpdateIndividualProfileRequest req = reqCapture.getValue(); + assertNull(req.getCustomPulldownFields().get("udf_pulldown_1")); + assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_1").toString()); + } + + private void setUserPulldownSelection(final String field, final String value) { + // Get the pulldown field collection for the user. + CustomFieldCollection pulldowns = user.getProfile().getCustomPulldownFields(); + if (pulldowns == null) { + pulldowns = new CustomFieldCollection<>(); + user.getProfile().setCustomPulldownFields(pulldowns); + } + + // Create the selection for the value. + PulldownSelection selection = new PulldownSelection(); + selection.setLabel(value); + + // Create the field/value pair and add it to the collection. + CustomPulldownFieldValue fieldValue = new CustomPulldownFieldValue(); + fieldValue.setName(field); // This is unused by the test, but it should be a udf_ identifier. + fieldValue.setLabel(field); + fieldValue.setSelection(selection); + pulldowns.add(fieldValue); + } + + private void replay() { + EasyMock.replay(api, cache); + } + + private void verify() { + EasyMock.verify(api, cache); + } +} \ No newline at end of file -- cgit v1.2.3 From 1a175649a383e11671e4c8c6754c204ed80fe3cd Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sat, 9 Apr 2016 10:04:46 -0700 Subject: Updating CCBProgressReporterTest --- tst/com/p4square/grow/ccb/CCBProgressReporterTest.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'tst') diff --git a/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java b/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java index 6854f22..63a973a 100644 --- a/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java +++ b/tst/com/p4square/grow/ccb/CCBProgressReporterTest.java @@ -101,10 +101,6 @@ public class CCBProgressReporterTest { verify(); assertTrue(reqCapture.hasCaptured()); UpdateIndividualProfileRequest req = reqCapture.getValue(); - - // Both the Grow Level and Grow Assessment fields should be updated. - assertEquals(1, req.getCustomPulldownFields().get("udf_pulldown_1").intValue()); - assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_1").toString()); assertEquals(1, req.getCustomPulldownFields().get("udf_pulldown_2").intValue()); assertEquals("2015-04-01", req.getCustomDateFields().get("udf_date_2").toString()); } -- cgit v1.2.3