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. --- .../ChurchCommunityBuilderIntegrationDriver.java | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java (limited to 'src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java') diff --git a/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java b/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java new file mode 100644 index 0000000..3aeca2c --- /dev/null +++ b/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java @@ -0,0 +1,50 @@ +package com.p4square.grow.ccb; + +import com.codahale.metrics.MetricRegistry; +import com.p4square.ccbapi.CCBAPI; +import com.p4square.ccbapi.CCBAPIClient; +import com.p4square.grow.config.Config; +import com.p4square.grow.frontend.IntegrationDriver; +import org.restlet.Context; +import org.restlet.security.Verifier; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * The ChurchCommunityBuilderIntegrationDriver is used to integrate Grow with Church Community Builder. + */ +public class ChurchCommunityBuilderIntegrationDriver implements IntegrationDriver { + + private final Context mContext; + private final MetricRegistry mMetricRegistry; + private final Config mConfig; + + private final CCBAPI mAPI; + + public ChurchCommunityBuilderIntegrationDriver(final Context context) { + mContext = context; + mConfig = (Config) context.getAttributes().get("com.p4square.grow.config"); + mMetricRegistry = (MetricRegistry) context.getAttributes().get("com.p4square.grow.metrics"); + + try { + CCBAPI api = new CCBAPIClient(new URI(mConfig.getString("CCBAPIURL", "")), + mConfig.getString("CCBAPIUser", ""), + mConfig.getString("CCBAPIPassword", "")); + + if (mMetricRegistry != null) { + api = new MonitoredCCBAPI(api, mMetricRegistry); + } + + mAPI = api; + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + @Override + public Verifier newUserAuthenticationVerifier() { + return new CCBUserVerifier(mAPI); + } +} -- cgit v1.2.3 From 6698ffbb300ff8e48b5f3fe59144c699d39ab094 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Tue, 22 Mar 2016 21:42:03 -0700 Subject: Integrating the ProgressReporter Using the new ProgressReporter interface in AssessmentResultsPage and ChapterCompletePage. --- .../f1oauth/FellowshipOneIntegrationDriver.java | 10 +++++++ src/com/p4square/grow/ccb/CCBProgressReporter.java | 32 ++++++++++++++++++++++ .../ChurchCommunityBuilderIntegrationDriver.java | 10 +++++++ .../grow/frontend/AssessmentResultsPage.java | 32 ++++++++-------------- .../grow/frontend/ChapterCompletePage.java | 27 ++++-------------- .../p4square/grow/frontend/IntegrationDriver.java | 9 ++++++ .../p4square/grow/frontend/ProgressReporter.java | 5 ++-- 7 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 src/com/p4square/grow/ccb/CCBProgressReporter.java (limited to 'src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java') diff --git a/src/com/p4square/f1oauth/FellowshipOneIntegrationDriver.java b/src/com/p4square/f1oauth/FellowshipOneIntegrationDriver.java index e72df5e..865f5d6 100644 --- a/src/com/p4square/f1oauth/FellowshipOneIntegrationDriver.java +++ b/src/com/p4square/f1oauth/FellowshipOneIntegrationDriver.java @@ -3,6 +3,7 @@ package com.p4square.f1oauth; import com.codahale.metrics.MetricRegistry; import com.p4square.grow.config.Config; import com.p4square.grow.frontend.IntegrationDriver; +import com.p4square.grow.frontend.ProgressReporter; import org.restlet.Context; import org.restlet.security.Verifier; @@ -17,6 +18,8 @@ public class FellowshipOneIntegrationDriver implements IntegrationDriver { private final Config mConfig; private final F1Access mAPI; + private final ProgressReporter mProgressReporter; + public FellowshipOneIntegrationDriver(final Context context) { mContext = context; mConfig = (Config) context.getAttributes().get("com.p4square.grow.config"); @@ -29,6 +32,8 @@ public class FellowshipOneIntegrationDriver implements IntegrationDriver { mConfig.getString("f1ChurchCode", "pfseawa"), F1Access.UserType.WEBLINK); mAPI.setMetricRegistry(mMetricRegistry); + + mProgressReporter = new F1ProgressReporter(mAPI); } /** @@ -42,4 +47,9 @@ public class FellowshipOneIntegrationDriver implements IntegrationDriver { public Verifier newUserAuthenticationVerifier() { return new SecondPartyVerifier(mContext, mAPI); } + + @Override + public ProgressReporter getProgressReporter() { + return mProgressReporter; + } } diff --git a/src/com/p4square/grow/ccb/CCBProgressReporter.java b/src/com/p4square/grow/ccb/CCBProgressReporter.java new file mode 100644 index 0000000..e2304fe --- /dev/null +++ b/src/com/p4square/grow/ccb/CCBProgressReporter.java @@ -0,0 +1,32 @@ +package com.p4square.grow.ccb; + +import com.p4square.ccbapi.CCBAPI; +import com.p4square.grow.frontend.ProgressReporter; +import org.restlet.security.User; + +import java.util.Date; + +/** + * A ProgressReporter which records progress in CCB. + * + * Except not really, because it's not implemented yet. + * This is just a placeholder until ccb-api-client-java has support for updating an individual. + */ +public class CCBProgressReporter implements ProgressReporter { + + private final CCBAPI mAPI; + + public CCBProgressReporter(final CCBAPI api) { + mAPI = api; + } + + @Override + public void reportAssessmentComplete(User user, String level, Date date, String results) { + // TODO + } + + @Override + public void reportChapterComplete(User user, String chapter, Date date) { + // TODO + } +} diff --git a/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java b/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java index 3aeca2c..48d143c 100644 --- a/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java +++ b/src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java @@ -5,6 +5,7 @@ import com.p4square.ccbapi.CCBAPI; import com.p4square.ccbapi.CCBAPIClient; import com.p4square.grow.config.Config; import com.p4square.grow.frontend.IntegrationDriver; +import com.p4square.grow.frontend.ProgressReporter; import org.restlet.Context; import org.restlet.security.Verifier; @@ -22,6 +23,8 @@ public class ChurchCommunityBuilderIntegrationDriver implements IntegrationDrive private final CCBAPI mAPI; + private final CCBProgressReporter mProgressReporter; + public ChurchCommunityBuilderIntegrationDriver(final Context context) { mContext = context; mConfig = (Config) context.getAttributes().get("com.p4square.grow.config"); @@ -38,6 +41,8 @@ public class ChurchCommunityBuilderIntegrationDriver implements IntegrationDrive mAPI = api; + mProgressReporter = new CCBProgressReporter(mAPI); + } catch (URISyntaxException e) { throw new RuntimeException(e); } @@ -47,4 +52,9 @@ public class ChurchCommunityBuilderIntegrationDriver implements IntegrationDrive public Verifier newUserAuthenticationVerifier() { return new CCBUserVerifier(mAPI); } + + @Override + public ProgressReporter getProgressReporter() { + return mProgressReporter; + } } diff --git a/src/com/p4square/grow/frontend/AssessmentResultsPage.java b/src/com/p4square/grow/frontend/AssessmentResultsPage.java index 9b66794..f1c924b 100644 --- a/src/com/p4square/grow/frontend/AssessmentResultsPage.java +++ b/src/com/p4square/grow/frontend/AssessmentResultsPage.java @@ -7,6 +7,7 @@ package com.p4square.grow.frontend; import java.util.Date; import java.util.Map; +import com.fasterxml.jackson.core.JsonProcessingException; import com.p4square.f1oauth.FellowshipOneIntegrationDriver; import freemarker.template.Template; @@ -30,6 +31,7 @@ import com.p4square.f1oauth.F1User; import com.p4square.grow.config.Config; import com.p4square.grow.provider.JsonEncodedProvider; +import org.restlet.security.User; /** * This page fetches the user's final score and displays the transitional page between @@ -103,30 +105,18 @@ public class AssessmentResultsPage extends FreeMarkerPageResource { } private void publishScoreInF1(Map results) { - if (!(getRequest().getClientInfo().getUser() instanceof F1User)) { - // Only useful if the user is from F1. - return; - } + final ProgressReporter reporter = mGrowFrontend.getThirdPartyIntegrationFactory().getProgressReporter(); - F1User user = (F1User) getRequest().getClientInfo().getUser(); + try { + final User user = getRequest().getClientInfo().getUser(); + final String level = results.get("result").toString(); + final Date completionDate = new Date(); + final String data = JsonEncodedProvider.MAPPER.writeValueAsString(results); - // Update the attribute. - String attributeName = "Assessment Complete - " + results.get("result"); + reporter.reportAssessmentComplete(user, level, completionDate, data); - try { - Attribute attribute = new Attribute(attributeName); - attribute.setStartDate(new Date()); - attribute.setComment(JsonEncodedProvider.MAPPER.writeValueAsString(results)); - - F1API f1 = ((FellowshipOneIntegrationDriver) mGrowFrontend.getThirdPartyIntegrationFactory()) - .getF1Access().getAuthenticatedApi(user); - if (!f1.addAttribute(user.getIdentifier(), attribute)) { - LOG.error("addAttribute failed for " + user.getIdentifier() - + " with attribute " + attributeName); - } - } catch (Exception e) { - LOG.error("addAttribute failed for " + user.getIdentifier() - + " with attribute " + attributeName, e); + } catch (JsonProcessingException e) { + LOG.error("Failed to generate json " + e.getMessage(), e); } } diff --git a/src/com/p4square/grow/frontend/ChapterCompletePage.java b/src/com/p4square/grow/frontend/ChapterCompletePage.java index 2dd1ecf..35abc43 100644 --- a/src/com/p4square/grow/frontend/ChapterCompletePage.java +++ b/src/com/p4square/grow/frontend/ChapterCompletePage.java @@ -32,6 +32,7 @@ import com.p4square.grow.config.Config; import com.p4square.grow.model.TrainingRecord; import com.p4square.grow.provider.Provider; import com.p4square.grow.provider.TrainingRecordProvider; +import org.restlet.security.User; /** * This resource displays the transitional page between chapters. @@ -159,30 +160,12 @@ public class ChapterCompletePage extends FreeMarkerPageResource { } private void assignAttribute() { - if (!(getRequest().getClientInfo().getUser() instanceof F1User)) { - // Only useful if the user is from F1. - return; - } - - F1User user = (F1User) getRequest().getClientInfo().getUser(); + final ProgressReporter reporter = mGrowFrontend.getThirdPartyIntegrationFactory().getProgressReporter(); - // Update the attribute. - String attributeName = "Training Complete - " + mChapter; + final User user = getRequest().getClientInfo().getUser(); + final Date completionDate = new Date(); - try { - Attribute attribute = new Attribute(attributeName); - attribute.setStartDate(new Date()); - - F1API f1 = ((FellowshipOneIntegrationDriver) mGrowFrontend.getThirdPartyIntegrationFactory()) - .getF1Access().getAuthenticatedApi(user); - if (!f1.addAttribute(user.getIdentifier(), attribute)) { - LOG.error("addAttribute failed for " + user.getIdentifier() - + " with attribute " + attributeName); - } - } catch (Exception e) { - LOG.error("addAttribute failed for " + user.getIdentifier() - + " with attribute " + attributeName, e); - } + reporter.reportChapterComplete(user, mChapter, completionDate); } /** diff --git a/src/com/p4square/grow/frontend/IntegrationDriver.java b/src/com/p4square/grow/frontend/IntegrationDriver.java index 3370116..b9c3508 100644 --- a/src/com/p4square/grow/frontend/IntegrationDriver.java +++ b/src/com/p4square/grow/frontend/IntegrationDriver.java @@ -14,4 +14,13 @@ public interface IntegrationDriver { * @return A Verifier. */ Verifier newUserAuthenticationVerifier(); + + /** + * Return a ProgressReporter for this Church Management System. + * + * The ProgressReporter should be thread-safe. + * + * @return The ProgressReporter. + */ + ProgressReporter getProgressReporter(); } diff --git a/src/com/p4square/grow/frontend/ProgressReporter.java b/src/com/p4square/grow/frontend/ProgressReporter.java index 9b57ff4..2f36832 100644 --- a/src/com/p4square/grow/frontend/ProgressReporter.java +++ b/src/com/p4square/grow/frontend/ProgressReporter.java @@ -20,10 +20,11 @@ public interface ProgressReporter { void reportAssessmentComplete(User user, String level, Date date, String results); /** + * Report that the User completed the chapter. * * @param user The user who completed the chapter. - * @param chapter The chatper completed. - * @param date Teh completion date. + * @param chapter The chapter completed. + * @param date The completion date. */ void reportChapterComplete(User user, String chapter, Date date); } -- 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 'src/com/p4square/grow/ccb/ChurchCommunityBuilderIntegrationDriver.java') 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