Skip to content

Commit

Permalink
Merge pull request #533 from OpenSRP/only-catch-checked-widget-except…
Browse files Browse the repository at this point in the history
…ions

Only catch checked widget exceptions
  • Loading branch information
githengi authored Dec 10, 2020
2 parents 2f91bd4 + 0f146d3 commit 2c1efd9
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,14 @@ public static class INTENT_KEY {
public static final String MESSAGE_TYPE = "message_type";
}

public interface RESULT_CODE {
int RUNTIME_EXCEPTION_OCCURRED = 8037;
}

public interface RESULT_INTENT {
String RUNTIME_EXCEPTION = "runtime_exception";
}

public static class MESSAGE_TYPE {
public static final String GLOBAL_VALUES = "global_values";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.vijay.jsonwizard.interactors;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;

import com.vijay.jsonwizard.R;
import com.vijay.jsonwizard.constants.JsonFormConstants;
import com.vijay.jsonwizard.fragments.JsonFormFragment;
import com.vijay.jsonwizard.interfaces.CommonListener;
import com.vijay.jsonwizard.interfaces.FormWidgetFactory;
import com.vijay.jsonwizard.utils.Utils;
import com.vijay.jsonwizard.widgets.BarcodeFactory;
import com.vijay.jsonwizard.widgets.ButtonFactory;
import com.vijay.jsonwizard.widgets.CheckBoxFactory;
Expand Down Expand Up @@ -49,6 +54,8 @@
import java.util.Map;
import java.util.Set;

import timber.log.Timber;

/**
* Created by vijay on 5/19/15.
*/
Expand Down Expand Up @@ -219,14 +226,28 @@ private void fetchViews(List<View> viewsFromJson, String stepName, JsonFormFragm
if (views.size() > 0) {
viewsFromJson.addAll(views);
}
} catch (Exception e) {
Log.e(TAG,
"Exception occurred in making view : Exception is : "
+ e.getMessage());
e.printStackTrace();
} catch (RuntimeException e) {
closeActivityAfterRuntimeException(formFragment.getActivity(), e);
} catch(Exception e) {
Timber.e(e, "Exception encountered while creating form widget!");
}
}

private void closeActivityAfterRuntimeException(Activity activity, RuntimeException e) {
Timber.e(e);

Utils.showToast(activity, activity.getString(R.string.form_load_error));

Bundle bundle = new Bundle();
bundle.putSerializable(JsonFormConstants.RESULT_INTENT.RUNTIME_EXCEPTION, e);

Intent intent = new Intent();
intent.putExtras(bundle);

activity.setResult(JsonFormConstants.RESULT_CODE.RUNTIME_EXCEPTION_OCCURRED, intent);
activity.finish();
}

public final Set<String> getDefaultTranslatableWidgetFields() {
return defaultTranslatableWidgetFields;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.vijay.jsonwizard.utils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
Expand Down Expand Up @@ -844,6 +846,25 @@ public static boolean isEmptyJsonArray(JSONArray jsonArray) {
return jsonArray == null || jsonArray.length() == 0;
}

public static void showAlertDialog(Context context, String title, String message,
String negativeBtnTxt, String positiveBtnTxt,
DialogInterface.OnClickListener negativeBtnListener,
DialogInterface.OnClickListener positiveBtnListener) {

AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context, R.style.AppThemeAlertDialog).setTitle(title)
.setMessage(message);

if (negativeBtnListener != null) {
alertDialogBuilder.setNegativeButton(negativeBtnTxt, negativeBtnListener);
}

if (positiveBtnListener != null) {
alertDialogBuilder.setPositiveButton(positiveBtnTxt, positiveBtnListener);
}

alertDialogBuilder.create().show();
}

public static boolean isEmptyJsonObject(JSONObject jsonObject) {
return jsonObject == null || jsonObject.length() == 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class BarcodeFactory implements FormWidgetFactory {

@Override
public List<View> getViewsFromJson(String stepName, Context context, JsonFormFragment formFragment, JSONObject jsonObject, CommonListener listener) throws Exception {
return attachJson(stepName, context, formFragment, jsonObject, true);
return getViewsFromJson(stepName, context, formFragment, jsonObject, listener, false);
}

@Override
Expand All @@ -67,62 +67,60 @@ public Set<String> getCustomTranslatableWidgetFields() {
@Override
public List<View> getViewsFromJson(String stepName, final Context context,
JsonFormFragment formFragment, final JSONObject jsonObject,
CommonListener listener, boolean popup) {
CommonListener listener, boolean popup) throws Exception {
return attachJson(stepName, context, formFragment, jsonObject, popup);
}

private List<View> attachJson(String stepName, final Context context, JsonFormFragment formFragment, final JSONObject jsonObject, boolean popup) {
private List<View> attachJson(String stepName, final Context context, JsonFormFragment formFragment, final JSONObject jsonObject, boolean popup) throws Exception {
List<View> views = new ArrayList<>(1);
try {
String relevance = jsonObject.optString(JsonFormConstants.RELEVANCE);
String calculation = jsonObject.optString(JsonFormConstants.CALCULATION);
final String constraints = jsonObject.optString(JsonFormConstants.CONSTRAINTS);
String value = jsonObject.optString(JsonFormConstants.VALUE, null);

RelativeLayout rootLayout = getRootLayout(context);
final int canvasId = ViewUtil.generateViewId();
rootLayout.setId(canvasId);
final MaterialEditText editText = createEditText(rootLayout, jsonObject, canvasId, stepName, popup);
if (value != null && !checkValue(value)) {
editText.setText(value);

String relevance = jsonObject.optString(JsonFormConstants.RELEVANCE);
String calculation = jsonObject.optString(JsonFormConstants.CALCULATION);
final String constraints = jsonObject.optString(JsonFormConstants.CONSTRAINTS);
String value = jsonObject.optString(JsonFormConstants.VALUE, null);

RelativeLayout rootLayout = getRootLayout(context);
final int canvasId = ViewUtil.generateViewId();
rootLayout.setId(canvasId);
final MaterialEditText editText = createEditText(rootLayout, jsonObject, canvasId, stepName, popup);
if (value != null && !checkValue(value)) {
editText.setText(value);
}

editText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addOnClickActions(context, editText, jsonObject.optString(JsonFormConstants.BARCODE_TYPE));
}
});

editText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editText.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
editText.setText("");
return true;
}
});

GenericTextWatcher textWatcher = new GenericTextWatcher(stepName, formFragment, editText);
textWatcher.addOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
addOnClickActions(context, editText, jsonObject.optString(JsonFormConstants.BARCODE_TYPE));
}
});
}
});

editText.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
editText.setText("");
return true;
}
});

GenericTextWatcher textWatcher = new GenericTextWatcher(stepName, formFragment, editText);
textWatcher.addOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
addOnClickActions(context, editText, jsonObject.optString(JsonFormConstants.BARCODE_TYPE));
}
}
});
addScanButton(context, jsonObject, editText, rootLayout);

addScanButton(context, jsonObject, editText, rootLayout);
editText.addTextChangedListener(textWatcher);
attachRefreshLogic(context, relevance, calculation, constraints, editText);

editText.addTextChangedListener(textWatcher);
attachRefreshLogic(context, relevance, calculation, constraints, editText);
((JsonApi) context).addFormDataView(editText);

((JsonApi) context).addFormDataView(editText);
views.add(rootLayout);

views.add(rootLayout);
} catch (Exception e) {
Timber.e(e);
}

return views;
}
Expand Down
3 changes: 3 additions & 0 deletions android-json-form-wizard/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,7 @@
<string name="current_corrupted_form">(Current Corrupted Form)</string>
<string name="cannot_select_corrupted_form_rollback">You cannot select this form because it\'s corrupted!</string>

<string name="error_title">Error</string>
<string name="form_load_error">Sorry, a fatal error occurred when loading the form. Please contact a developer for further assistance.</string>

</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.vijay.jsonwizard.interactors;

import android.content.Intent;
import android.view.View;

import com.vijay.jsonwizard.BaseTest;
import com.vijay.jsonwizard.R;
import com.vijay.jsonwizard.activities.JsonFormActivity;
import com.vijay.jsonwizard.constants.JsonFormConstants;
import com.vijay.jsonwizard.fragments.JsonFormFragment;
import com.vijay.jsonwizard.interfaces.CommonListener;

import org.json.JSONObject;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.reflect.Whitebox;
import org.robolectric.Robolectric;
import org.robolectric.util.ReflectionHelpers;

import java.util.ArrayList;

/**
* Created by Vincent Karuri on 09/12/2020
*/
public class JsonFormInteractorTest extends BaseTest {

private JsonFormInteractor jsonFormInteractor;

@Captor
private ArgumentCaptor<Intent> intentArgumentCaptor;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
jsonFormInteractor = JsonFormInteractor.getInstance();
}

@After
public void tearDown() {
ReflectionHelpers.setField(jsonFormInteractor, "INSTANCE", null);
}

@Test
public void testFetchViewsShouldSetCorrectResultForRTE() throws Exception {
ReflectionHelpers.setField(jsonFormInteractor, "map", null);

JsonFormActivity activity = Mockito.spy(Robolectric.buildActivity(JsonFormActivity.class, getJsonFormActivityIntent()).create().start().get());
JsonFormFragment jsonFormFragment = Mockito.mock(JsonFormFragment.class);
Mockito.doReturn(activity).when(jsonFormFragment).getActivity();

Whitebox.invokeMethod(jsonFormInteractor, "fetchViews", new ArrayList<View>(), "",
jsonFormFragment, "", new JSONObject(), Mockito.mock(CommonListener.class), false);

Mockito.verify(activity).getString(R.string.form_load_error);
Mockito.verify(activity).setResult(Mockito.eq(JsonFormConstants.RESULT_CODE.RUNTIME_EXCEPTION_OCCURRED), intentArgumentCaptor.capture());
Mockito.verify(activity).finish();

Intent intent = intentArgumentCaptor.getValue();
Assert.assertTrue(intent.getExtras().getSerializable(JsonFormConstants.RESULT_INTENT.RUNTIME_EXCEPTION) instanceof RuntimeException);

activity.finish();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.vijay.jsonwizard.utils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.view.View;
import android.widget.LinearLayout;
Expand All @@ -27,11 +29,13 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.reflect.internal.WhiteboxImpl;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowDialog;
import org.robolectric.util.ReflectionHelpers;

import java.io.ByteArrayInputStream;
Expand Down Expand Up @@ -418,4 +422,22 @@ public void testRemoveDeletedInvalidFieldsShouldDeleteRespectiveInvalidFields()
Assert.assertEquals(1, invalidFields.size());
Assert.assertEquals(prefix + "field3", invalidFields.keySet().iterator().next());
}


@Test
public void testShowAlertDialogShouldDisplayAlertDialogCorrectly() {
DialogInterface.OnClickListener onClickListener = Mockito.mock(DialogInterface.OnClickListener.class);

Utils.showAlertDialog(RuntimeEnvironment.application, "title", "message", "no", "yes", onClickListener, onClickListener);

AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
Assert.assertNotNull(dialog);

dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
Mockito.verify(onClickListener).onClick(ArgumentMatchers.any(DialogInterface.class), ArgumentMatchers.anyInt());

Mockito.reset(onClickListener);
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
Mockito.verify(onClickListener).onClick(ArgumentMatchers.any(DialogInterface.class), ArgumentMatchers.anyInt());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import java.util.List;

public class BarcodeFactorTest extends BaseTest {
public class BarcodeFactoryTest extends BaseTest {
private BarcodeFactory factory;
@Mock
private JsonFormActivity context;
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION_NAME=1.14.7.2-SNAPSHOT
VERSION_NAME=1.14.8.0-SNAPSHOT
VERSION_CODE=1
GROUP=org.smartregister
POM_SETTING_DESCRIPTION=OpenSRP Client Native Form Json Wizard
Expand Down

0 comments on commit 2c1efd9

Please sign in to comment.