package co.smartreceipts.android.ocr;
import android.content.Context;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.io.File;
import co.smartreceipts.android.analytics.Analytics;
import co.smartreceipts.android.apis.hosts.ServiceManager;
import co.smartreceipts.android.aws.s3.S3Manager;
import co.smartreceipts.android.identity.IdentityManager;
import co.smartreceipts.android.ocr.apis.OcrService;
import co.smartreceipts.android.ocr.apis.model.OcrResponse;
import co.smartreceipts.android.ocr.apis.model.RecognitionResponse;
import co.smartreceipts.android.ocr.apis.model.RecongitionRequest;
import co.smartreceipts.android.ocr.purchases.OcrPurchaseTracker;
import co.smartreceipts.android.ocr.push.OcrPushMessageReceiver;
import co.smartreceipts.android.ocr.push.OcrPushMessageReceiverFactory;
import co.smartreceipts.android.push.PushManager;
import co.smartreceipts.android.settings.UserPreferenceManager;
import co.smartreceipts.android.settings.catalog.UserPreference;
import co.smartreceipts.android.utils.Feature;
import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@RunWith(RobolectricTestRunner.class)
public class OcrManagerTest {
private static final String IMG_NAME = "123456789.jpg";
private static final String ID = "id";
// Class under test
OcrManager ocrManager;
Context context = RuntimeEnvironment.application;
@Mock
S3Manager s3Manager;
@Mock
IdentityManager identityManager;
@Mock
ServiceManager ocrServiceManager;
@Mock
PushManager pushManager;
@Mock
OcrPurchaseTracker ocrPurchaseTracker;
@Mock
OcrPushMessageReceiverFactory ocrPushMessageReceiverFactory;
@Mock
OcrPushMessageReceiver pushMessageReceiver;
@Mock
UserPreferenceManager userPreferenceManager;
@Mock
Analytics analytics;
@Mock
Feature ocrFeature;
@Mock
File file;
@Mock
OcrService ocrService;
@Mock
RecognitionResponse recognitionResponse;
@Mock
RecognitionResponse.Recognition recognition;
@Mock
RecognitionResponse.RecognitionData recognitionData;
@Mock
OcrResponse ocrResponse;
TestObserver<OcrResponse> testObserver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
testObserver = new TestObserver<>();
when(ocrFeature.isEnabled()).thenReturn(true);
when(identityManager.isLoggedIn()).thenReturn(true);
when(ocrPurchaseTracker.hasAvailableScans()).thenReturn(true);
when(ocrPushMessageReceiverFactory.get()).thenReturn(pushMessageReceiver);
when(s3Manager.upload(file, "ocr/")).thenReturn(Observable.just("https://aws.amazon.com/smartreceipts/ocr/" + IMG_NAME));
when(ocrServiceManager.getService(OcrService.class)).thenReturn(ocrService);
when(recognitionResponse.getRecognition()).thenReturn(recognition);
when(recognition.getId()).thenReturn(ID);
when(recognition.getData()).thenReturn(recognitionData);
when(recognitionData.getRecognitionData()).thenReturn(ocrResponse);
when(ocrService.scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false))).thenReturn(Observable.just(recognitionResponse));
when(ocrService.scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, true))).thenReturn(Observable.just(recognitionResponse));
when(pushMessageReceiver.getOcrPushResponse()).thenReturn(Observable.just(new Object()));
when(ocrService.getRecognitionResult(ID)).thenReturn(Observable.just(recognitionResponse));
when(userPreferenceManager.get(UserPreference.Misc.OcrIsEnabled)).thenReturn(true);
when(userPreferenceManager.get(UserPreference.Misc.OcrIncognitoMode)).thenReturn(false);
ocrManager = new OcrManager(context, s3Manager, identityManager, ocrServiceManager, pushManager, ocrPurchaseTracker, userPreferenceManager, analytics, ocrPushMessageReceiverFactory, ocrFeature);
}
@Test
public void scanWhenFeatureIsDisabled() {
when(ocrFeature.isEnabled()).thenReturn(false);
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verifyZeroInteractions(s3Manager, ocrServiceManager, pushManager, pushMessageReceiver);
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
}
@Test
public void scanWhenNotLoggedIn() {
when(identityManager.isLoggedIn()).thenReturn(false);
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verifyZeroInteractions(s3Manager, ocrServiceManager, pushManager, pushMessageReceiver);
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
}
@Test
public void scanWithNoAvailableScans() {
when(ocrPurchaseTracker.hasAvailableScans()).thenReturn(false);
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verifyZeroInteractions(s3Manager, ocrServiceManager, pushManager, pushMessageReceiver);
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
}
@Test
public void scanWhenNotEnabled() {
when(userPreferenceManager.get(UserPreference.Misc.OcrIsEnabled)).thenReturn(false);
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verifyZeroInteractions(s3Manager, ocrServiceManager, pushManager, pushMessageReceiver);
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
}
@Test
public void scanButS3UploadFails() {
when(s3Manager.upload(file, "ocr/")).thenReturn(Observable.error(new Exception("test")));
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
verify(ocrService, never()).scanReceipt(any(RecongitionRequest.class));
verify(ocrService, never()).getRecognitionResult(anyString());
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
verify(pushMessageReceiver, never()).getOcrPushResponse();
verifyZeroInteractions(ocrServiceManager);
}
@Test
public void scanButS3ReturnsUnexpectedUrl() {
when(s3Manager.upload(file, "ocr/")).thenReturn(Observable.just("https://test.com"));
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
verify(ocrService, never()).scanReceipt(any(RecongitionRequest.class));
verify(ocrService, never()).getRecognitionResult(anyString());
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
verify(pushMessageReceiver, never()).getOcrPushResponse();
verifyZeroInteractions(ocrServiceManager);
}
@Test
public void scanButRecognitionRequestFails() {
when(ocrService.scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false))).thenReturn(Observable.error(new Exception("test")));
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(ocrService).scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false));
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
verify(ocrService, never()).getRecognitionResult(anyString());
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
verify(pushMessageReceiver, never()).getOcrPushResponse();
}
@Test
public void scanButRecognitionResponseIsInvalidWithNullId() {
when(recognition.getId()).thenReturn(null);
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(ocrService).scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false));
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
verify(ocrService, never()).getRecognitionResult(anyString());
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
verify(pushMessageReceiver, never()).getOcrPushResponse();
}
@Test
public void scanButGetRecognitionResultails() {
when(ocrService.getRecognitionResult(ID)).thenReturn(Observable.error(new Exception("test")));
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(new OcrResponse());
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(ocrService).scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false));
verify(ocrPurchaseTracker, never()).decrementRemainingScans();
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
}
@Test
public void scanCompletes() {
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(ocrResponse);
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(ocrService).scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false));
verify(ocrPurchaseTracker).decrementRemainingScans();
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
}
@Test
public void scanCompletesWithIncognitoModeOn() {
when(userPreferenceManager.get(UserPreference.Misc.OcrIncognitoMode)).thenReturn(true);
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(ocrResponse);
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(ocrService).scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, true));
verify(ocrPurchaseTracker).decrementRemainingScans();
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
}
@Test
public void scanCompletesEvenIfPushMessageTimesOutStillContinuesProcessing() {
when(pushMessageReceiver.getOcrPushResponse()).thenReturn(Observable.error(new Exception("timeout")));
ocrManager.scan(file).subscribe(testObserver);
testObserver.awaitTerminalEvent();
testObserver.assertValue(ocrResponse);
testObserver.onComplete();
testObserver.assertNoErrors();
verify(s3Manager).upload(file, "ocr/");
verify(ocrService).scanReceipt(new RecongitionRequest("ocr/" + IMG_NAME, false));
verify(ocrPurchaseTracker).decrementRemainingScans();
verify(pushManager).registerReceiver(pushMessageReceiver);
verify(pushManager).unregisterReceiver(pushMessageReceiver);
}
}