Skip to content

Commit 94c6636

Browse files
Better javadoc and tests for specific scenarios of the Unknown User Activation
1 parent 3ec8831 commit 94c6636

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

iterableapi/src/main/java/com/iterable/iterableapi/IterableUnknownUserHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public interface IterableUnknownUserHandler {
1414
/**
1515
* Called when the SDK fetches unknown user activation criteria successfully.
1616
* <p>
17+
* Fires after the criteria response has been persisted to local storage, so it is safe to call
18+
* {@code track}, {@code trackPurchase}, etc. from this callback and have those events evaluated
19+
* against the just-arrived criteria set.
20+
* <p>
1721
* Fires on every criteria fetch, implementation should take that into consideration.
1822
* @param criteria the criteria returned by the server
1923
*/

iterableapi/src/test/java/com/iterable/iterableapi/IterableApiCriteriaFetchTests.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static android.os.Looper.getMainLooper;
44
import static junit.framework.Assert.assertFalse;
5+
import static junit.framework.Assert.assertNotNull;
56
import static junit.framework.Assert.assertTrue;
67
import static org.robolectric.Shadows.shadowOf;
78

@@ -20,6 +21,7 @@
2021
import java.io.IOException;
2122
import java.util.concurrent.TimeUnit;
2223
import java.util.concurrent.atomic.AtomicBoolean;
24+
import java.util.concurrent.atomic.AtomicInteger;
2325
import java.util.concurrent.atomic.AtomicReference;
2426

2527
import okhttp3.mockwebserver.MockResponse;
@@ -243,6 +245,7 @@ public void testCriteriaCallbackOnFailure() throws Exception {
243245

244246
AtomicBoolean succeeded = new AtomicBoolean(false);
245247
AtomicBoolean failed = new AtomicBoolean(false);
248+
AtomicReference<String> failureReason = new AtomicReference<>(null);
246249
IterableConfig config = new IterableConfig.Builder()
247250
.setEnableUnknownUserActivation(true)
248251
.setUnknownUserHandler(new IterableUnknownUserHandler() {
@@ -255,6 +258,7 @@ public void onCriteriaReceived(JSONObject criteria) {
255258
@Override
256259
public void onCriteriaFetchFailed(String reason) {
257260
failed.set(true);
261+
failureReason.set(reason);
258262
}
259263
})
260264
.build();
@@ -265,5 +269,46 @@ public void onCriteriaFetchFailed(String reason) {
265269

266270
assertTrue("onCriteriaFetchFailed should be called when the criteria fetch fails", failed.get());
267271
assertFalse("onCriteriaReceived should not be called on a failed fetch", succeeded.get());
272+
assertNotNull("onCriteriaFetchFailed should receive a failure reason", failureReason.get());
273+
assertFalse("Failure reason should not be empty", failureReason.get().isEmpty());
274+
}
275+
276+
@Test
277+
public void testCriteriaCallbackFiresOnEveryFetch() throws Exception {
278+
// Flush the criteria fetch triggered by setUp() while no callback is installed,
279+
// then reset tracking so only the callback-observed fetches below are counted.
280+
shadowOf(getMainLooper()).idle();
281+
IterableApi.getInstance().setVisitorUsageTracked(false);
282+
283+
String criteriaJson = "{\"criteriaSets\":[{\"criteriaId\":\"1\"}]}";
284+
// One response per fetch.
285+
dispatcher.enqueueResponse("/" + IterableConstants.ENDPOINT_CRITERIA_LIST,
286+
new MockResponse().setResponseCode(200).setBody(criteriaJson));
287+
dispatcher.enqueueResponse("/" + IterableConstants.ENDPOINT_CRITERIA_LIST,
288+
new MockResponse().setResponseCode(200).setBody(criteriaJson));
289+
290+
AtomicInteger receivedCount = new AtomicInteger(0);
291+
IterableConfig config = new IterableConfig.Builder()
292+
.setEnableUnknownUserActivation(true)
293+
.setUnknownUserHandler(new IterableUnknownUserHandler() {
294+
@Override
295+
public void onUnknownUserCreated(String userId) {}
296+
@Override
297+
public void onCriteriaReceived(JSONObject criteria) {
298+
receivedCount.incrementAndGet();
299+
}
300+
})
301+
.build();
302+
303+
IterableApi.initialize(getContext(), "apiKey", config);
304+
305+
// Each enable of visitor usage tracking triggers a criteria fetch; the callback
306+
// should fire once per fetch, matching the documented "fires on every fetch" contract.
307+
IterableApi.getInstance().setVisitorUsageTracked(true);
308+
shadowOf(getMainLooper()).idle();
309+
IterableApi.getInstance().setVisitorUsageTracked(true);
310+
shadowOf(getMainLooper()).idle();
311+
312+
Assert.assertEquals("onCriteriaReceived should fire once per fetch", 2, receivedCount.get());
268313
}
269314
}

0 commit comments

Comments
 (0)