diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index f5397409c..3a45918c4 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -35,8 +35,9 @@ import java.io.InvalidObjectException; public class LoyaltyCardEditActivity extends AppCompatActivity { private static final String TAG = "CardLocker"; + protected static final String NO_BARCODE = "_NO_BARCODE_"; - private static final int SELECT_BARCODE_REQUEST = 1; + protected static final int SELECT_BARCODE_REQUEST = 1; EditText storeFieldEdit; EditText noteFieldEdit; @@ -229,42 +230,49 @@ public class LoyaltyCardEditActivity extends AppCompatActivity if(cardIdFieldView.getText().length() > 0 && barcodeTypeField.getText().length() > 0) { - String formatString = barcodeTypeField.getText().toString(); - final BarcodeFormat format = BarcodeFormat.valueOf(formatString); - final String cardIdString = cardIdFieldView.getText().toString(); - - if(barcodeImage.getHeight() == 0) + if(barcodeTypeField.getText().equals(NO_BARCODE)) { - Log.d(TAG, "ImageView size is not known known at start, waiting for load"); - // The size of the ImageView is not yet available as it has not - // yet been drawn. Wait for it to be drawn so the size is available. - barcodeImage.getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() - { - @Override - public void onGlobalLayout() - { - if (Build.VERSION.SDK_INT < 16) - { - barcodeImage.getViewTreeObserver().removeGlobalOnLayoutListener(this); - } - else - { - barcodeImage.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - - Log.d(TAG, "ImageView size now known"); - new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute(); - } - }); + barcodeImageLayout.setVisibility(View.GONE); } else { - Log.d(TAG, "ImageView size known known, creating barcode"); - new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute(); - } + String formatString = barcodeTypeField.getText().toString(); + final BarcodeFormat format = BarcodeFormat.valueOf(formatString); + final String cardIdString = cardIdFieldView.getText().toString(); - barcodeImageLayout.setVisibility(View.VISIBLE); + if(barcodeImage.getHeight() == 0) + { + Log.d(TAG, "ImageView size is not known known at start, waiting for load"); + // The size of the ImageView is not yet available as it has not + // yet been drawn. Wait for it to be drawn so the size is available. + barcodeImage.getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() + { + @Override + public void onGlobalLayout() + { + if (Build.VERSION.SDK_INT < 16) + { + barcodeImage.getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + else + { + barcodeImage.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + + Log.d(TAG, "ImageView size now known"); + new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute(); + } + }); + } + else + { + Log.d(TAG, "ImageView size known known, creating barcode"); + new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute(); + } + + barcodeImageLayout.setVisibility(View.VISIBLE); + } } View.OnClickListener captureCallback = new View.OnClickListener() @@ -366,6 +374,13 @@ public class LoyaltyCardEditActivity extends AppCompatActivity String cardId = cardIdFieldView.getText().toString(); String barcodeType = barcodeTypeField.getText().toString(); + // We do not want to save the no barcode string to the database + // it is simply an empty there for no barcode + if(barcodeType.equals(NO_BARCODE)) + { + barcodeType = ""; + } + if(store.isEmpty()) { Snackbar.make(storeFieldEdit, R.string.noStoreError, Snackbar.LENGTH_LONG).show(); @@ -493,7 +508,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity cardIdView.setText(contents); final TextView barcodeTypeField = findViewById(R.id.barcodeType); - barcodeTypeField.setText(format); + // Set special NO_BARCODE value to prevent onResume from overwriting it + barcodeTypeField.setText(format.isEmpty() ? LoyaltyCardEditActivity.NO_BARCODE : format); onResume(); } } diff --git a/app/src/test/java/protect/card_locker/BarcodeSelectorActivityTest.java b/app/src/test/java/protect/card_locker/BarcodeSelectorActivityTest.java index 0d53e506f..993355c56 100644 --- a/app/src/test/java/protect/card_locker/BarcodeSelectorActivityTest.java +++ b/app/src/test/java/protect/card_locker/BarcodeSelectorActivityTest.java @@ -63,6 +63,8 @@ public class BarcodeSelectorActivityTest { // Clicking button should create "empty" barcode activity.findViewById(R.id.noBarcode).performClick(); Intent resultIntent = shadowOf(activity).getResultIntent(); + + // The BarcodeSelectorActivity should return an empty string assertEquals("", resultIntent.getStringExtra(BarcodeSelectorActivity.BARCODE_FORMAT)); assertEquals("abcdefg", resultIntent.getStringExtra(BarcodeSelectorActivity.BARCODE_CONTENTS)); } diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java index e0b6b7441..e139de488 100644 --- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java +++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java @@ -126,7 +126,16 @@ public class LoyaltyCardViewActivityTest assertEquals(store, card.store); assertEquals(note, card.note); assertEquals(cardId, card.cardId); - assertEquals(barcodeType, card.barcodeType); + + // The special "No barcode" string shouldn't actually be written to the loyalty card + if(barcodeType.equals(LoyaltyCardEditActivity.NO_BARCODE)) + { + assertEquals("", card.barcodeType); + } + else + { + assertEquals(barcodeType, card.barcodeType); + } assertNotNull(card.headerColor); assertNotNull(card.headerTextColor); } @@ -155,10 +164,10 @@ public class LoyaltyCardViewActivityTest assertNotNull(bundle); Intent resultIntent = new Intent(intent); - Bundle resultBuddle = new Bundle(); - resultBuddle.putString(Intents.Scan.RESULT, BARCODE_DATA); - resultBuddle.putString(Intents.Scan.RESULT_FORMAT, BARCODE_TYPE); - resultIntent.putExtras(resultBuddle); + Bundle resultBundle = new Bundle(); + resultBundle.putString(Intents.Scan.RESULT, BARCODE_DATA); + resultBundle.putString(Intents.Scan.RESULT_FORMAT, BARCODE_TYPE); + resultIntent.putExtras(resultBundle); // Respond to image capture, success shadowOf(activity).receiveResult( @@ -167,6 +176,38 @@ public class LoyaltyCardViewActivityTest resultIntent); } + /** + * Initiate and complete a barcode selection, either in success + * or in failure + */ + private void selectBarcodeWithResult(final Activity activity, final int buttonId, final String barcodeData, final String barcodeType, final boolean success) throws IOException + { + // Start image capture + final Button captureButton = activity.findViewById(buttonId); + captureButton.performClick(); + + ShadowActivity.IntentForResult intentForResult = shadowOf(activity).peekNextStartedActivityForResult(); + assertNotNull(intentForResult); + + Intent intent = intentForResult.intent; + assertNotNull(intent); + + Bundle bundle = intent.getExtras(); + assertNotNull(bundle); + + Intent resultIntent = new Intent(intent); + Bundle resultBundle = new Bundle(); + resultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, barcodeType); + resultBundle.putString(BarcodeSelectorActivity.BARCODE_CONTENTS, barcodeData); + resultIntent.putExtras(resultBundle); + + // Respond to barcode selection, success + shadowOf(activity).receiveResult( + intent, + success ? Activity.RESULT_OK : Activity.RESULT_CANCELED, + resultIntent); + } + private void checkFieldProperties(final Activity activity, final int id, final int visibility, final String contents) { @@ -539,7 +580,33 @@ public class LoyaltyCardViewActivityTest activityController.resume(); // Save and check the loyalty card - saveLoyaltyCardWithArguments(activity, "store", "note", BARCODE_DATA, "", false); + saveLoyaltyCardWithArguments(activity, "store", "note", BARCODE_DATA, LoyaltyCardEditActivity.NO_BARCODE, false); + } + + @Test + public void removeBarcodeFromLoyaltyCard() throws IOException + { + ActivityController activityController = createActivityWithLoyaltyCard(true); + Activity activity = (Activity)activityController.get(); + DBHelper db = new DBHelper(activity); + + db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE); + + activityController.start(); + activityController.visible(); + activityController.resume(); + + // First check if the card is as expected + checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", BARCODE_DATA, BARCODE_TYPE); + + // Complete empty barcode selection successfully + selectBarcodeWithResult(activity, R.id.enterButton, BARCODE_DATA, "", true); + + // Check if the barcode type is NO_BARCODE as expected + checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", BARCODE_DATA, LoyaltyCardEditActivity.NO_BARCODE); + + // Check if the special NO_BARCODE string doesn't get saved + saveLoyaltyCardWithArguments(activity, "store", "note", BARCODE_DATA, LoyaltyCardEditActivity.NO_BARCODE, false); } @Test