diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/MenuFileActivityIntegrationTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/MenuFileActivityIntegrationTest.java deleted file mode 100644 index 1e845f010e..0000000000 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/MenuFileActivityIntegrationTest.java +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Paintroid: An image manipulation application for Android. - * Copyright (C) 2010-2021 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.paintroid.test.espresso; - -import android.app.Activity; -import android.app.Instrumentation; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.MediaStore; - -import org.catrobat.paintroid.FileIO; -import org.catrobat.paintroid.MainActivity; -import org.catrobat.paintroid.R; -import org.catrobat.paintroid.common.Constants; -import org.catrobat.paintroid.presenter.MainActivityPresenter; -import org.catrobat.paintroid.test.espresso.util.BitmapLocationProvider; -import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider; -import org.catrobat.paintroid.test.espresso.util.EspressoUtils; -import org.catrobat.paintroid.test.utils.ScreenshotOnFailRule; -import org.catrobat.paintroid.tools.ToolType; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Objects; - -import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.rule.GrantPermissionRule; - -import static org.catrobat.paintroid.test.espresso.util.UiInteractions.touchAt; -import static org.catrobat.paintroid.test.espresso.util.wrappers.DrawingSurfaceInteraction.onDrawingSurfaceView; -import static org.catrobat.paintroid.test.espresso.util.wrappers.ToolBarViewInteraction.onToolBarView; -import static org.catrobat.paintroid.test.espresso.util.wrappers.TopBarViewInteraction.onTopBarView; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.core.AllOf.allOf; -import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; - -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.pressBack; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.pressMenuKey; -import static androidx.test.espresso.action.ViewActions.replaceText; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intending; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup; -import static androidx.test.espresso.matcher.ViewMatchers.isClickable; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withSpinnerText; -import static androidx.test.espresso.matcher.ViewMatchers.withText; - -@RunWith(AndroidJUnit4.class) -public class MenuFileActivityIntegrationTest { - - private static ArrayList deletionFileList = null; - @Rule - public IntentsTestRule launchActivityRule = new IntentsTestRule<>(MainActivity.class); - - @Rule - public ScreenshotOnFailRule screenshotOnFailRule = new ScreenshotOnFailRule(); - - @ClassRule - public static GrantPermissionRule grantPermissionRule = EspressoUtils.grantPermissionRulesVersionCheck(); - - private MainActivity activity; - - @Before - public void setUp() { - onToolBarView().performSelectTool(ToolType.BRUSH); - deletionFileList = new ArrayList<>(); - activity = launchActivityRule.getActivity(); - } - - @After - public void tearDown() { - for (File file : deletionFileList) { - if (file != null && file.exists()) { - assertTrue(file.delete()); - } - } - } - - @Test - public void testNewEmptyDrawingWithSave() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onDrawingSurfaceView() - .checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_new_image)) - .perform(click()); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("test987654")); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - onDrawingSurfaceView() - .checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE); - } - - @Test - public void testLoadImageDialog() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)) - .perform(click()); - - onView(withText(R.string.menu_load_image)) - .check(matches(isDisplayed())); - onView(withText(R.string.dialog_warning_new_image)) - .check(matches(isDisplayed())); - onView(withText(R.string.save_button_text)) - .check(matches(isDisplayed())); - onView(withText(R.string.discard_button_text)) - .check(matches(isDisplayed())); - } - - @Test - public void testLoadImageDialogIntentCancel() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - Instrumentation.ActivityResult resultCancel = new Instrumentation.ActivityResult(Activity.RESULT_CANCELED, new Intent()); - intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultCancel); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)).perform(click()); - onView(withText(R.string.discard_button_text)).perform(click()); - onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()); - - onDrawingSurfaceView() - .checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE); - } - - @Test - public void testLoadImageDialogIntentOK() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.HALFWAY_RIGHT_MIDDLE)); - onDrawingSurfaceView() - .checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE); - - Intent intent = new Intent(); - intent.setData(createTestImageFile()); - Instrumentation.ActivityResult resultOK = new Instrumentation.ActivityResult(Activity.RESULT_OK, intent); - intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultOK); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)).perform(click()); - onView(withText(R.string.discard_button_text)).perform(click()); - onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()); - - onDrawingSurfaceView() - .checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE); - } - - @Test - public void testLoadImageDialogOnBackPressed() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)).perform(click()); - - pressBack(); - - onDrawingSurfaceView() - .check(matches(isDisplayed())); - } - - @Test - public void testOnHelpDisabled() { - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.help_title)).check(matches(not(isClickable()))); - } - - @Test - public void testWarningDialogOnNewImage() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_new_image)).perform(click()); - - onView(withText(R.string.dialog_warning_new_image)).check(matches(isDisplayed())); - onView(withText(R.string.save_button_text)).check(matches(isDisplayed())); - onView(withText(R.string.discard_button_text)).check(matches(isDisplayed())); - - pressBack(); - - onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()); - } - - @Test - public void testNewEmptyDrawingWithDiscard() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_new_image)) - .perform(click()); - - onView(withText(R.string.discard_button_text)) - .perform(click()); - - onView(withText(R.string.dialog_warning_new_image)) - .check(doesNotExist()); - - onDrawingSurfaceView() - .checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE); - } - - @Test - public void testNewEmptyDrawingDialogOnBackPressed() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_new_image)).perform(click()); - - onView(withText(R.string.dialog_warning_new_image)).check(matches(isDisplayed())); - onView(withText(R.string.save_button_text)).check(matches(isDisplayed())); - onView(withText(R.string.discard_button_text)).check(matches(isDisplayed())); - - pressBack(); - - onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()); - - onDrawingSurfaceView() - .checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE); - } - - @Test - public void testSavedStateChangeAfterSave() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - assertFalse(activity.model.isSaved()); - - pressMenuKey(); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)).perform(click()); - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("test98765")); - - onView(withText(R.string.save_button_text)).perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - assertTrue(activity.model.isSaved()); - } - - @Test - public void testSaveImage() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)).perform(click()); - onView(withText(R.string.save_button_text)).perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - if (!activity.model.isOpenedFromCatroid()) { - assertNotSame("", MainActivityPresenter.getPathFromUri(this.activity, activity.model.getSavedPictureUri())); - } - - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - } - - @Test - public void testSaveCopy() { - launchActivityRule.getActivity().getPreferences(Context.MODE_PRIVATE) - .edit() - .clear() - .commit(); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)).perform(click()); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("save1")); - - onView(withText(R.string.save_button_text)).perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - if (!activity.model.isOpenedFromCatroid()) { - assertNotSame("", MainActivityPresenter.getPathFromUri(this.activity, activity.model.getSavedPictureUri())); - } - - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - File oldFile = new File(activity.model.getSavedPictureUri().toString()); - - onView(withText(R.string.pocketpaint_no)).perform(click()); - onView(withText(R.string.pocketpaint_ok)).perform(click()); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.HALFWAY_BOTTOM_MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_copy)).perform(click()); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("copy1")); - - onView(withText(R.string.save_button_text)).perform(click()); - - File newFile = new File(activity.model.getSavedPictureUri().toString()); - - assertNotSame("Changes to saved", oldFile, newFile); - - assertNotNull(activity.model.getSavedPictureUri()); - if (!activity.model.isOpenedFromCatroid()) { - assertNotSame("", MainActivityPresenter.getPathFromUri(this.activity, activity.model.getSavedPictureUri())); - } - - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - } - - @Test - public void testAskForSaveAfterSavedOnce() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)).perform(click()); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("AskForSaveAfterSavedOnce")); - - onView(withText(R.string.save_button_text)).perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - pressBack(); - onView(withText(R.string.menu_quit)).check(matches(isDisplayed())); - } - - @Test - public void testShowOverwriteDialogAfterSavingAgain() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)).perform(click()); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("12345test12345")); - - onView(withText(R.string.save_button_text)).perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - onView(withText(R.string.overwrite_button_text)) - .check(matches(isDisplayed())); - } - - @Test - public void testCheckImageNumberIncrementAfterSaveWithStandardName() { - FileIO.filename = "image"; - int imageNumber = launchActivityRule.getActivity().getPresenter().getImageNumber(); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - int newImageNumber = launchActivityRule.getActivity().getPresenter().getImageNumber(); - assertEquals(imageNumber + 1, newImageNumber); - } - - @Test - public void testCheckImageNumberSameAfterSaveWithNonStandardName() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - int imageNumber = launchActivityRule.getActivity().getPresenter().getImageNumber(); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("test9876")); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - int newImageNumber = launchActivityRule.getActivity().getPresenter().getImageNumber(); - assertEquals(imageNumber, newImageNumber); - } - - @Test - public void testCheckSaveFileWithDifferentFormats() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_info_title)).check(matches(isDisplayed())); - onView(withId(R.id.pocketpaint_image_name_save_text)).check(matches(isDisplayed())); - onView(withId(R.id.pocketpaint_save_dialog_spinner)).check(matches(isDisplayed())); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(allOf(is(instanceOf(String.class)), - is("png"))).inRoot(isPlatformPopup()).perform(click()); - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText(Constants.TEMP_PICTURE_NAME)); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - File oldFile = new File(activity.model.getSavedPictureUri().toString()); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(allOf(is(instanceOf(String.class)), - is("jpg"))).inRoot(isPlatformPopup()).perform(click()); - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText(Constants.TEMP_PICTURE_NAME)); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - File newFile = new File(activity.model.getSavedPictureUri().toString()); - - assertNotSame(oldFile, newFile); - } - - @Test - public void testCheckSaveImageDialogShowJPGSpinnerText() { - - createImageIntent(); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)).perform(click()); - onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()); - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .check(matches(withSpinnerText(containsString("jpg")))); - } - - @Test - public void testCheckSaveImageDialogShowPNGSpinnerText() { - FileIO.compressFormat = Bitmap.CompressFormat.PNG; - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .check(matches(withSpinnerText(containsString("png")))); - } - - @Test - public void testCheckSaveImageDialogShowORASpinnerText() { - FileIO.isCatrobatImage = true; - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .check(matches(withSpinnerText(containsString("ora")))); - } - - @Test - public void testCheckSaveImageDialogShowsSavedImageOptions() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - String imageName = "test12345"; - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText(imageName)); - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(allOf(is(instanceOf(String.class)), - is("png"))).inRoot(isPlatformPopup()).perform(click()); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withText(imageName)) - .check(matches(isDisplayed())); - onView(withText("png")) - .check(matches(isDisplayed())); - } - - @Test - public void testCheckCopyIsAlwaysDefaultOptions() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_copy)) - .perform(click()); - - int imageNumber = launchActivityRule.getActivity().getPresenter().getImageNumber(); - - onView(withText("png")) - .check(matches(isDisplayed())); - onView(withText("image" + imageNumber)) - .check(matches(isDisplayed())); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(allOf(is(instanceOf(String.class)), - is("png"))).inRoot(isPlatformPopup()).perform(click()); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_copy)) - .perform(click()); - - imageNumber = launchActivityRule.getActivity().getPresenter().getImageNumber(); - - onView(withText("png")) - .check(matches(isDisplayed())); - onView(withText("image" + imageNumber)) - .check(matches(isDisplayed())); - } - - private void createImageIntent() { - Intent intent = new Intent(); - intent.setData(createTestImageFile()); - Instrumentation.ActivityResult resultOK = new Instrumentation.ActivityResult(Activity.RESULT_OK, intent); - intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultOK); - } - - private Uri createTestImageFile() { - Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888); - - ContentValues contentValues = new ContentValues(); - contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "testfile.jpg"); - contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES); - } - - ContentResolver resolver = activity.getContentResolver(); - Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); - try { - OutputStream fos = resolver.openOutputStream(Objects.requireNonNull(imageUri)); - assertTrue(bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)); - assert fos != null; - fos.close(); - } catch (IOException e) { - throw new AssertionError("Picture file could not be created.", e); - } - - File imageFile = new File(imageUri.getPath(), "testfile.jpg"); - - deletionFileList.add(imageFile); - return imageUri; - } - - @Test - public void testLoadImageTransparency() { - Intent intent = new Intent(); - intent.setData(createTestImageFile()); - Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, intent); - intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)) - .perform(click()); - - onToolBarView() - .performSelectTool(ToolType.ERASER); - - onDrawingSurfaceView() - .checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onDrawingSurfaceView() - .checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE); - } - - private void addUriToDeletionFileList(Uri uri) { - deletionFileList.add(new File(Objects.requireNonNull(uri.getPath()))); - } -} diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/MenuFileActivityIntegrationTest.kt b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/MenuFileActivityIntegrationTest.kt new file mode 100644 index 0000000000..a330a5fab3 --- /dev/null +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/MenuFileActivityIntegrationTest.kt @@ -0,0 +1,554 @@ +/* + * Paintroid: An image manipulation application for Android. + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.paintroid.test.espresso + +import android.app.Activity +import android.app.Instrumentation.ActivityResult +import android.content.ContentValues +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.Color +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.MediaStore +import androidx.test.espresso.Espresso.onData +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.pressBack +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.pressMenuKey +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.assertion.ViewAssertions.doesNotExist +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction +import androidx.test.espresso.intent.rule.IntentsTestRule +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers.isClickable +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withSpinnerText +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.GrantPermissionRule +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import org.catrobat.paintroid.FileIO +import org.catrobat.paintroid.MainActivity +import org.catrobat.paintroid.R +import org.catrobat.paintroid.common.Constants +import org.catrobat.paintroid.presenter.MainActivityPresenter +import org.catrobat.paintroid.test.espresso.util.BitmapLocationProvider +import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider.HALFWAY_BOTTOM_MIDDLE +import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider.HALFWAY_RIGHT_MIDDLE +import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider.MIDDLE +import org.catrobat.paintroid.test.espresso.util.EspressoUtils.grantPermissionRulesVersionCheck +import org.catrobat.paintroid.test.espresso.util.UiInteractions.touchAt +import org.catrobat.paintroid.test.espresso.util.wrappers.DrawingSurfaceInteraction.onDrawingSurfaceView +import org.catrobat.paintroid.test.espresso.util.wrappers.ToolBarViewInteraction +import org.catrobat.paintroid.test.espresso.util.wrappers.TopBarViewInteraction.onTopBarView +import org.catrobat.paintroid.test.utils.ScreenshotOnFailRule +import org.catrobat.paintroid.tools.ToolType +import org.hamcrest.Matchers.`is` +import org.hamcrest.Matchers.containsString +import org.hamcrest.Matchers.instanceOf +import org.hamcrest.core.AllOf.allOf +import org.hamcrest.core.IsNot +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNotSame +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.ClassRule +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import java.io.File +import java.io.IOException +import java.lang.AssertionError + +@RunWith(AndroidJUnit4::class) +class MenuFileActivityIntegrationTest { + @get:Rule + var launchActivityRule = IntentsTestRule(MainActivity::class.java) + + @get:Rule + var screenshotOnFailRule = ScreenshotOnFailRule() + + private lateinit var activity: MainActivity + + companion object { + private lateinit var deletionFileList: ArrayList + + @get:ClassRule + var grantPermissionRule: GrantPermissionRule = grantPermissionRulesVersionCheck() + } + + @Before + fun setUp() { + ToolBarViewInteraction.onToolBarView().performSelectTool(ToolType.BRUSH) + deletionFileList = ArrayList() + activity = launchActivityRule.activity + } + + @After + fun tearDown() { + for (file in deletionFileList) { + if (file != null && file.exists()) { + assertTrue(file.delete()) + } + } + } + + @Test + fun testNewEmptyDrawingWithSave() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onDrawingSurfaceView().checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_new_image)).perform(click()) + runBlocking { + onView(withText(R.string.save_button_text)) + .perform(click()) + delay(100) + } + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("test987654")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + onDrawingSurfaceView().checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE) + } + + @Test + fun testLoadImageDialog() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(click()) + onView(withText(R.string.menu_load_image)).check(matches(isDisplayed())) + onView(withText(R.string.dialog_warning_new_image)).check(matches(isDisplayed())) + onView(withText(R.string.save_button_text)).check(matches(isDisplayed())) + onView(withText(R.string.discard_button_text)).check(matches(isDisplayed())) + } + + @Test + fun testLoadImageDialogIntentCancel() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + val resultCancel = ActivityResult(Activity.RESULT_CANCELED, Intent()) + Intents.intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultCancel) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(click()) + onView(withText(R.string.discard_button_text)).perform(click()) + onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()) + onDrawingSurfaceView().checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE) + } + + @Test + fun testLoadImageDialogIntentOK() { + onDrawingSurfaceView().perform(touchAt(HALFWAY_RIGHT_MIDDLE)) + onDrawingSurfaceView().checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE) + val intent = Intent() + intent.data = createTestImageFile() + val resultOK = ActivityResult(Activity.RESULT_OK, intent) + Intents.intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultOK) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(click()) + onView(withText(R.string.discard_button_text)).perform(click()) + onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()) + onDrawingSurfaceView().checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE) + } + + @Test + fun testLoadImageDialogOnBackPressed() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(click()) + pressBack() + onDrawingSurfaceView().check(matches(isDisplayed())) + } + + @Test + fun testOnHelpDisabled() { + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.help_title)).check(matches(IsNot.not(isClickable()))) + } + + @Test + fun testWarningDialogOnNewImage() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_new_image)).perform(click()) + onView(withText(R.string.dialog_warning_new_image)).check(matches(isDisplayed())) + onView(withText(R.string.save_button_text)).check(matches(isDisplayed())) + onView(withText(R.string.discard_button_text)).check(matches(isDisplayed())) + pressBack() + onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()) + } + + @Test + fun testNewEmptyDrawingWithDiscard() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_new_image)).perform(click()) + onView(withText(R.string.discard_button_text)).perform(click()) + onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()) + onDrawingSurfaceView().checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE) + } + + @Test + fun testNewEmptyDrawingDialogOnBackPressed() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_new_image)).perform(click()) + onView(withText(R.string.dialog_warning_new_image)).check(matches(isDisplayed())) + onView(withText(R.string.save_button_text)).check(matches(isDisplayed())) + onView(withText(R.string.discard_button_text)).check(matches(isDisplayed())) + pressBack() + onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()) + onDrawingSurfaceView().checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE) + } + + @Test + fun testSavedStateChangeAfterSave() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + assertFalse(activity.model.isSaved) + pressMenuKey() + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("test98765")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + assertTrue(activity.model.isSaved) + } + + @Test + fun testSaveImage() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + if (!activity.model.isOpenedFromCatroid) { + assertNotSame( + "", + MainActivityPresenter.getPathFromUri(activity, activity.model.savedPictureUri) + ) + } + addUriToDeletionFileList(activity.model.savedPictureUri) + } + + @Test + fun testSaveCopy() { + launchActivityRule.activity.getPreferences(Context.MODE_PRIVATE) + .edit() + .clear() + .commit() + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("save1")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + if (!activity.model.isOpenedFromCatroid) { + assertNotSame( + "", + MainActivityPresenter.getPathFromUri(activity, activity.model.savedPictureUri) + ) + } + addUriToDeletionFileList(activity.model.savedPictureUri) + val oldFile = File(activity.model.savedPictureUri.toString()) + onView(withText(R.string.pocketpaint_no)).perform(click()) + onView(withText(R.string.pocketpaint_ok)).perform(click()) + onDrawingSurfaceView().perform(touchAt(HALFWAY_BOTTOM_MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_copy)).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("copy1")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + val newFile = File(activity.model.savedPictureUri.toString()) + assertNotSame("Changes to saved", oldFile, newFile) + assertNotNull(activity.model.savedPictureUri) + if (!activity.model.isOpenedFromCatroid) { + assertNotSame( + "", + MainActivityPresenter.getPathFromUri(activity, activity.model.savedPictureUri) + ) + } + addUriToDeletionFileList(activity.model.savedPictureUri) + } + + @Test + fun testAskForSaveAfterSavedOnce() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("AskForSaveAfterSavedOnce")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + pressBack() + onView(withText(R.string.menu_quit)).check(matches(isDisplayed())) + } + + @Test + fun testShowOverwriteDialogAfterSavingAgain() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("12345test12345")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + onView(withText(R.string.overwrite_button_text)).check(matches(isDisplayed())) + } + + @Test + fun testCheckImageNumberIncrementAfterSaveWithStandardName() { + FileIO.filename = "image" + val imageNumber = launchActivityRule.activity.presenter.imageNumber + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + val newImageNumber = launchActivityRule.activity.presenter.imageNumber + assertEquals((imageNumber + 1).toLong(), newImageNumber.toLong()) + } + + @Test + fun testCheckImageNumberSameAfterSaveWithNonStandardName() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + val imageNumber = launchActivityRule.activity.presenter.imageNumber + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText("test9876")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + val newImageNumber = launchActivityRule.activity.presenter.imageNumber + assertEquals(imageNumber.toLong(), newImageNumber.toLong()) + } + + @Test + fun testCheckSaveFileWithDifferentFormats() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_save_info_title)).check(matches(isDisplayed())) + onView(withId(R.id.pocketpaint_image_name_save_text)).check(matches(isDisplayed())) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).check(matches(isDisplayed())) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(click()) + onData(allOf(`is`(instanceOf(String::class.java)), `is`("png"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText(Constants.TEMP_PICTURE_NAME)) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + val oldFile = File(activity.model.savedPictureUri.toString()) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(click()) + onData(allOf(`is`(instanceOf(String::class.java)), `is`("jpg"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(replaceText(Constants.TEMP_PICTURE_NAME)) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + val newFile = File(activity.model.savedPictureUri.toString()) + assertNotSame(oldFile, newFile) + } + + @Test + fun testCheckSaveImageDialogShowJPGSpinnerText() { + createImageIntent() + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(click()) + onView(withText(R.string.dialog_warning_new_image)).check(doesNotExist()) + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)) + .check(matches(withSpinnerText(containsString("jpg")))) + } + + @Test + fun testCheckSaveImageDialogShowPNGSpinnerText() { + FileIO.compressFormat = Bitmap.CompressFormat.PNG + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)) + .check(matches(withSpinnerText(containsString("png")))) + } + + @Test + fun testCheckSaveImageDialogShowORASpinnerText() { + FileIO.isCatrobatImage = true + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)) + .check(matches(withSpinnerText(containsString("ora")))) + } + + @Test + fun testCheckSaveImageDialogShowsSavedImageOptions() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + val imageName = "test12345" + onView(withId(R.id.pocketpaint_image_name_save_text)).perform(replaceText(imageName)) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(click()) + onData(allOf(`is`(instanceOf(String::class.java)), `is`("png"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(click()) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(click()) + onView(withText(imageName)).check(matches(isDisplayed())) + onView(withText("png")).check(matches(isDisplayed())) + } + + @Test + fun testCheckCopyIsAlwaysDefaultOptions() { + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_copy)).perform(click()) + var imageNumber = launchActivityRule.activity.presenter.imageNumber + onView(withText("png")).check(matches(isDisplayed())) + onView(withText("image$imageNumber")).check(matches(isDisplayed())) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(click()) + onData(allOf(`is`(instanceOf(String::class.java)), `is`("png"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(click()) + runBlocking { + onView(withText(R.string.save_button_text)).perform(click()) + delay(100) + } + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_copy)).perform(click()) + imageNumber = launchActivityRule.activity.presenter.imageNumber + onView(withText("png")).check(matches(isDisplayed())) + onView(withText("image$imageNumber")).check(matches(isDisplayed())) + } + + private fun createImageIntent() { + val intent = Intent() + intent.data = createTestImageFile() + val resultOK = ActivityResult(Activity.RESULT_OK, intent) + Intents.intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultOK) + } + + private fun createTestImageFile(): Uri? { + val bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888) + val contentValues = ContentValues() + contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "testfile.jpg") + contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) + } + val resolver = activity.contentResolver + val imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) + try { + val fos = imageUri?.let { resolver.openOutputStream(it) } + assertTrue(bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)) + assert(fos != null) + fos?.close() + } catch (e: IOException) { + throw AssertionError("Picture file could not be created.", e) + } + val imageFile = File(imageUri?.path, "testfile.jpg") + deletionFileList.add(imageFile) + return imageUri + } + + @Test + fun testLoadImageTransparency() { + val intent = Intent() + intent.data = createTestImageFile() + val result = ActivityResult(Activity.RESULT_OK, intent) + Intents.intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(click()) + ToolBarViewInteraction.onToolBarView().performSelectTool(ToolType.ERASER) + onDrawingSurfaceView().checkPixelColor(Color.BLACK, BitmapLocationProvider.MIDDLE) + onDrawingSurfaceView().perform(touchAt(MIDDLE)) + onDrawingSurfaceView().checkPixelColor(Color.TRANSPARENT, BitmapLocationProvider.MIDDLE) + } + + private fun addUriToDeletionFileList(uri: Uri) { + uri.path?.let { + deletionFileList.add(File(it)) + } + } +} diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/OraFileFormatIntegrationTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/OraFileFormatIntegrationTest.java deleted file mode 100644 index f7dbdb825d..0000000000 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/OraFileFormatIntegrationTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Paintroid: An image manipulation application for Android. - * Copyright (C) 2010-2021 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.catrobat.paintroid.test.espresso; - -import android.app.Activity; -import android.app.Instrumentation; -import android.content.Intent; -import android.net.Uri; - -import org.catrobat.paintroid.MainActivity; -import org.catrobat.paintroid.R; -import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider; -import org.catrobat.paintroid.test.espresso.util.EspressoUtils; -import org.catrobat.paintroid.test.utils.ScreenshotOnFailRule; -import org.hamcrest.core.AllOf; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.ArrayList; -import java.util.Objects; - -import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.rule.GrantPermissionRule; - -import static org.catrobat.paintroid.test.espresso.util.UiInteractions.touchAt; -import static org.catrobat.paintroid.test.espresso.util.wrappers.DrawingSurfaceInteraction.onDrawingSurfaceView; -import static org.catrobat.paintroid.test.espresso.util.wrappers.LayerMenuViewInteraction.onLayerMenuView; -import static org.catrobat.paintroid.test.espresso.util.wrappers.TopBarViewInteraction.onTopBarView; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.core.AllOf.allOf; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.replaceText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intending; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; - -@RunWith(AndroidJUnit4.class) -public class OraFileFormatIntegrationTest { - - private static ArrayList deletionFileList = null; - - @Rule - public IntentsTestRule launchActivityRule = new IntentsTestRule<>(MainActivity.class); - - @Rule - public ScreenshotOnFailRule screenshotOnFailRule = new ScreenshotOnFailRule(); - - @ClassRule - public static GrantPermissionRule grantPermissionRule = EspressoUtils.grantPermissionRulesVersionCheck(); - - private MainActivity activity; - - @Before - public void setUp() { - deletionFileList = new ArrayList<>(); - activity = launchActivityRule.getActivity(); - } - - @After - public void tearDown() { - for (File file : deletionFileList) { - if (file != null && file.exists()) { - assertTrue(file.delete()); - } - } - } - - @Test - public void testSaveAsOraFile() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(allOf(is(instanceOf(String.class)), - is("ora"))).inRoot(isPlatformPopup()).perform(click()); - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("test1337")); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - assertNotNull(activity.model.getSavedPictureUri()); - addUriToDeletionFileList(activity.model.getSavedPictureUri()); - } - - @Test - public void testSaveAndOverrideOraFile() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(allOf(is(instanceOf(String.class)), - is("ora"))).inRoot(isPlatformPopup()).perform(click()); - - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("OraOverride")); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - onView(withText(R.string.pocketpaint_no)).perform(click()); - onView(withText(R.string.pocketpaint_ok)).perform(click()); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.BOTTOM_MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - onView(withText(R.string.pocketpaint_overwrite_title)) - .check(matches(isDisplayed())); - - onView(withText(R.string.overwrite_button_text)) - .perform(click()); - - Uri imageUri = activity.model.getSavedPictureUri(); - - assertNotNull(imageUri); - addUriToDeletionFileList(imageUri); - } - - @Test - public void testOraFileWithMultipleLayersSaveAndLoad() { - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)); - - onLayerMenuView() - .performOpen() - .performAddLayer() - .checkLayerCount(2) - .performClose(); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.TOP_MIDDLE)); - - onLayerMenuView() - .performOpen() - .performAddLayer() - .checkLayerCount(3) - .performClose(); - - onDrawingSurfaceView() - .perform(touchAt(DrawingSurfaceLocationProvider.BOTTOM_MIDDLE)); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_save_image)) - .perform(click()); - - onView(withId(R.id.pocketpaint_save_dialog_spinner)) - .perform(click()); - onData(AllOf.allOf(is(instanceOf(String.class)), - is("ora"))).inRoot(isPlatformPopup()).perform(click()); - onView(withId(R.id.pocketpaint_image_name_save_text)) - .perform(replaceText("MoreLayersOraTest")); - - onView(withText(R.string.save_button_text)) - .perform(click()); - - Uri fileUri = activity.model.getSavedPictureUri(); - - assertNotNull(fileUri); - addUriToDeletionFileList(fileUri); - - Intent intent = new Intent(); - intent.setData(fileUri); - Instrumentation.ActivityResult resultOK = new Instrumentation.ActivityResult(Activity.RESULT_OK, intent); - intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultOK); - - onTopBarView() - .performOpenMoreOptions(); - - onView(withText(R.string.menu_load_image)) - .perform(click()); - - onLayerMenuView() - .performOpen() - .checkLayerCount(3); - } - - private void addUriToDeletionFileList(Uri uri) { - deletionFileList.add(new File(Objects.requireNonNull(uri.getPath()))); - } -} diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/OraFileFormatIntegrationTest.kt b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/OraFileFormatIntegrationTest.kt new file mode 100644 index 0000000000..c916ff9447 --- /dev/null +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/OraFileFormatIntegrationTest.kt @@ -0,0 +1,186 @@ +/* + * Paintroid: An image manipulation application for Android. + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.paintroid.test.espresso + +import android.app.Activity +import android.app.Instrumentation.ActivityResult +import android.content.Intent +import android.net.Uri +import androidx.test.espresso.Espresso.onData +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers +import androidx.test.espresso.intent.rule.IntentsTestRule +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.GrantPermissionRule +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import org.catrobat.paintroid.MainActivity +import org.catrobat.paintroid.R +import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider +import org.catrobat.paintroid.test.espresso.util.EspressoUtils.grantPermissionRulesVersionCheck +import org.catrobat.paintroid.test.espresso.util.UiInteractions.touchAt +import org.catrobat.paintroid.test.espresso.util.wrappers.DrawingSurfaceInteraction.onDrawingSurfaceView +import org.catrobat.paintroid.test.espresso.util.wrappers.LayerMenuViewInteraction +import org.catrobat.paintroid.test.espresso.util.wrappers.TopBarViewInteraction.onTopBarView +import org.catrobat.paintroid.test.utils.ScreenshotOnFailRule +import org.hamcrest.Matchers.`is` +import org.hamcrest.Matchers.instanceOf +import org.hamcrest.core.AllOf +import org.junit.After +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.ClassRule +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import java.io.File + +@RunWith(AndroidJUnit4::class) +class OraFileFormatIntegrationTest { + @get:Rule + var launchActivityRule = IntentsTestRule(MainActivity::class.java) + + @get:Rule + var screenshotOnFailRule = ScreenshotOnFailRule() + private lateinit var activity: MainActivity + + companion object { + private lateinit var deletionFileList: ArrayList + + @get:ClassRule + var grantPermissionRule: GrantPermissionRule = grantPermissionRulesVersionCheck() + } + + @Before + fun setUp() { + deletionFileList = ArrayList() + activity = launchActivityRule.activity + } + + @After + fun tearDown() { + for (file in deletionFileList) { + if (file != null && file.exists()) { + assertTrue(file.delete()) + } + } + } + + @Test + fun testSaveAsOraFile() { + onDrawingSurfaceView().perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(ViewActions.click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(ViewActions.click()) + onData(AllOf.allOf(`is`(instanceOf(String::class.java)), `is`("ora"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(ViewActions.click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(ViewActions.replaceText("test1337")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(ViewActions.click()) + delay(100) + } + assertNotNull(activity.model.savedPictureUri) + addUriToDeletionFileList(activity.model.savedPictureUri) + } + + @Test + fun testSaveAndOverrideOraFile() { + onDrawingSurfaceView().perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(ViewActions.click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(ViewActions.click()) + onData(AllOf.allOf(`is`(instanceOf(String::class.java)), `is`("ora"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(ViewActions.click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(ViewActions.replaceText("OraOverride")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(ViewActions.click()) + delay(100) + } + onView(withText(R.string.pocketpaint_no)).perform(ViewActions.click()) + onView(withText(R.string.pocketpaint_ok)).perform(ViewActions.click()) + onDrawingSurfaceView().perform(touchAt(DrawingSurfaceLocationProvider.BOTTOM_MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(ViewActions.click()) + runBlocking { + onView(withText(R.string.save_button_text)).perform(ViewActions.click()) + delay(100) + } + onView(withText(R.string.pocketpaint_overwrite_title)).check(ViewAssertions.matches(isDisplayed())) + onView(withText(R.string.overwrite_button_text)).perform(ViewActions.click()) + val imageUri = activity.model.savedPictureUri + assertNotNull(imageUri) + addUriToDeletionFileList(imageUri) + } + + @Test + fun testOraFileWithMultipleLayersSaveAndLoad() { + onDrawingSurfaceView().perform(touchAt(DrawingSurfaceLocationProvider.MIDDLE)) + LayerMenuViewInteraction.onLayerMenuView() + .performOpen() + .performAddLayer() + .checkLayerCount(2) + .performClose() + onDrawingSurfaceView().perform(touchAt(DrawingSurfaceLocationProvider.TOP_MIDDLE)) + LayerMenuViewInteraction.onLayerMenuView() + .performOpen() + .performAddLayer() + .checkLayerCount(3) + .performClose() + onDrawingSurfaceView().perform(touchAt(DrawingSurfaceLocationProvider.BOTTOM_MIDDLE)) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_save_image)).perform(ViewActions.click()) + onView(withId(R.id.pocketpaint_save_dialog_spinner)).perform(ViewActions.click()) + onData(AllOf.allOf(`is`(instanceOf(String::class.java)), `is`("ora"))) + .inRoot(RootMatchers.isPlatformPopup()).perform(ViewActions.click()) + onView(withId(R.id.pocketpaint_image_name_save_text)) + .perform(ViewActions.replaceText("MoreLayersOraTest")) + runBlocking { + onView(withText(R.string.save_button_text)).perform(ViewActions.click()) + delay(500) + } + val fileUri = activity.model.savedPictureUri + assertNotNull(fileUri) + addUriToDeletionFileList(fileUri) + val intent = Intent() + intent.data = fileUri + val resultOK = ActivityResult(Activity.RESULT_OK, intent) + Intents.intending(IntentMatchers.hasAction(Intent.ACTION_GET_CONTENT)).respondWith(resultOK) + onTopBarView().performOpenMoreOptions() + onView(withText(R.string.menu_load_image)).perform(ViewActions.click()) + LayerMenuViewInteraction.onLayerMenuView() + .performOpen() + .checkLayerCount(3) + } + + private fun addUriToDeletionFileList(uri: Uri) { + uri.path?.let { + deletionFileList.add(File(it)) + } + } +} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt b/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt index 4b26788582..3987dd6008 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt @@ -29,9 +29,9 @@ import androidx.annotation.ColorInt import androidx.annotation.StringRes import org.catrobat.paintroid.common.MainActivityConstants.ActivityRequestCode import org.catrobat.paintroid.dialog.PermissionInfoDialog.PermissionType -import org.catrobat.paintroid.iotasks.CreateFileAsync.CreateFileCallback +import org.catrobat.paintroid.iotasks.CreateFile.CreateFileCallback import org.catrobat.paintroid.iotasks.LoadImageAsync.LoadImageCallback -import org.catrobat.paintroid.iotasks.SaveImageAsync.SaveImageCallback +import org.catrobat.paintroid.iotasks.SaveImage.SaveImageCallback import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.ui.LayerAdapter diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/CreateFile.kt b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/CreateFile.kt new file mode 100644 index 0000000000..a335198c87 --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/CreateFile.kt @@ -0,0 +1,66 @@ +/* + * Paintroid: An image manipulation application for Android. + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.paintroid.iotasks + +import android.app.Activity +import android.util.Log +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.catrobat.paintroid.FileIO +import java.io.File +import java.lang.NullPointerException +import java.lang.ref.WeakReference + +class CreateFile( + callback: CreateFileCallback, + private val requestCode: Int, + private val filename: String?, + private val scopeIO: CoroutineScope +) { + private val callbackRef: WeakReference = WeakReference(callback) + + fun execute() { + val callback = callbackRef.get() + var file: File? = null + scopeIO.launch { + try { + file = FileIO.createNewEmptyPictureFile(filename, callback?.fileActivity) + } catch (e: NullPointerException) { + Log.e(TAG, "Can't create file", e) + } + withContext(Dispatchers.Main) { + if (callback != null && !callback.isFinishing) { + callback.onCreateFilePostExecute(requestCode, file) + } + } + } + } + + interface CreateFileCallback { + val fileActivity: Activity? + val isFinishing: Boolean + fun onCreateFilePostExecute(requestCode: Int, file: File?) + } + + companion object { + private val TAG = CreateFile::class.java.simpleName + } +} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/CreateFileAsync.java b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/CreateFileAsync.java deleted file mode 100644 index 12834b354c..0000000000 --- a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/CreateFileAsync.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Paintroid: An image manipulation application for Android. - * Copyright (C) 2010-2015 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.paintroid.iotasks; - -import android.app.Activity; -import android.os.AsyncTask; -import android.util.Log; - -import org.catrobat.paintroid.FileIO; - -import java.io.File; -import java.lang.ref.WeakReference; - -import androidx.annotation.Nullable; - -public class CreateFileAsync extends AsyncTask { - private static final String TAG = CreateFileAsync.class.getSimpleName(); - private WeakReference callbackRef; - private int requestCode; - private String filename; - - public CreateFileAsync(CreateFileCallback callback, int requestCode, @Nullable String filename) { - this.callbackRef = new WeakReference<>(callback); - this.requestCode = requestCode; - this.filename = filename; - } - - @Override - protected File doInBackground(Void... voids) { - CreateFileCallback callback = callbackRef.get(); - try { - return FileIO.createNewEmptyPictureFile(filename, callback.getFileActivity()); - } catch (NullPointerException e) { - Log.e(TAG, "Can't create file", e); - } - return null; - } - - @Override - protected void onPostExecute(File file) { - CreateFileCallback callback = callbackRef.get(); - if (callback != null && !callback.isFinishing()) { - callback.onCreateFilePostExecute(requestCode, file); - } - } - - public interface CreateFileCallback { - void onCreateFilePostExecute(int requestCode, File file); - Activity getFileActivity(); - boolean isFinishing(); - } -} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt new file mode 100644 index 0000000000..23adba04b4 --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt @@ -0,0 +1,137 @@ +/* + * Paintroid: An image manipulation application for Android. + * Copyright (C) 2010-2015 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.paintroid.iotasks + +import android.content.ContentResolver +import android.net.Uri +import android.util.Log +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.catrobat.paintroid.FileIO +import org.catrobat.paintroid.common.Constants +import org.catrobat.paintroid.tools.Workspace +import java.io.IOException +import java.lang.ref.WeakReference + +class SaveImage( + activity: SaveImageCallback, + private val requestCode: Int, + private val workspace: Workspace, + private var uri: Uri?, + private val saveAsCopy: Boolean, + private val scopeIO: CoroutineScope +) { + private val callbackRef: WeakReference = WeakReference(activity) + + companion object { + private val TAG = SaveImage::class.java.simpleName + } + + fun execute() { + val callback = callbackRef.get() + if (callback == null || callback.isFinishing) { + return + } else { + callback.onSaveImagePreExecute(requestCode) + } + + var currentUri: Uri? = null + scopeIO.launch { + try { + val bitmap = workspace.bitmapOfAllLayers + val fileName = FileIO.getDefaultFileName() + val fileExistsValue = FileIO.checkIfDifferentFile(fileName) + currentUri = if (FileIO.isCatrobatImage) { + val bitmapList = workspace.bitmapLisOfAllLayers + if (uri != null && fileExistsValue == Constants.IS_ORA) { + setUriToFormatUri(fileExistsValue) + OpenRasterFileFormatConversion.saveOraFileToUri( + bitmapList, + uri, + fileName, + bitmap, + callback.contentResolver + ) + } else { + val imageUri = OpenRasterFileFormatConversion.exportToOraFile( + bitmapList, + fileName, + bitmap, + callback.contentResolver + ) + FileIO.currentFileNameOra = fileName + FileIO.uriFileOra = imageUri + imageUri + } + } else { + if (uri != null && (FileIO.catroidFlag || fileExistsValue != Constants.IS_NO_FILE)) { + FileIO.saveBitmapToUri(uri, callback.contentResolver, bitmap) + } else { + val imageUri = + FileIO.saveBitmapToFile(fileName, bitmap, callback.contentResolver) + if (FileIO.ending == ".png") { + FileIO.currentFileNamePng = fileName + FileIO.uriFilePng = imageUri + } else { + FileIO.currentFileNameJpg = fileName + FileIO.uriFileJpg = imageUri + } + imageUri + } + } + } catch (e: Exception) { + when (e) { + is IOException -> Log.d(TAG, "Can't save image file", e) + is NullPointerException -> Log.e(TAG, "Can't load image file", e) + } + } + + withContext(Dispatchers.Main) { + if (!callback.isFinishing) { + callback.onSaveImagePostExecute(requestCode, currentUri, saveAsCopy) + } + } + } + } + + private fun setUriToFormatUri(formatCode: Int) { + if (formatCode == Constants.IS_JPG) { + if (FileIO.uriFileJpg != null) { + uri = FileIO.uriFileJpg + } + } else if (formatCode == Constants.IS_PNG) { + if (FileIO.uriFilePng != null) { + uri = FileIO.uriFilePng + } + } else { + if (FileIO.uriFileOra != null) { + uri = FileIO.uriFileOra + } + } + } + + interface SaveImageCallback { + val contentResolver: ContentResolver + val isFinishing: Boolean + fun onSaveImagePreExecute(requestCode: Int) + fun onSaveImagePostExecute(requestCode: Int, uri: Uri?, saveAsCopy: Boolean) + } +} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImageAsync.kt b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImageAsync.kt deleted file mode 100644 index c4a4ca0ee5..0000000000 --- a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImageAsync.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Paintroid: An image manipulation application for Android. - * Copyright (C) 2010-2015 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.catrobat.paintroid.iotasks - -import android.content.ContentResolver -import android.net.Uri -import android.os.AsyncTask -import android.util.Log -import org.catrobat.paintroid.FileIO -import org.catrobat.paintroid.common.Constants -import org.catrobat.paintroid.tools.Workspace -import java.io.IOException -import java.lang.ref.WeakReference - -class SaveImageAsync(activity: SaveImageCallback, private val requestCode: Int, workspace: Workspace, uri: Uri?, saveAsCopy: Boolean) : AsyncTask() { - private val callbackRef: WeakReference = WeakReference(activity) - private var uri: Uri? - private val saveAsCopy: Boolean - private val workspace: Workspace - override fun onPreExecute() { - val callback = callbackRef.get() - if (callback == null || callback.isFinishing) { - cancel(false) - } else { - callback.onSaveImagePreExecute(requestCode) - } - } - - override fun doInBackground(vararg params: Void?): Uri? { - val callback = callbackRef.get() - if (callback != null && !callback.isFinishing) { - try { - val bitmap = workspace.bitmapOfAllLayers - val fileName = FileIO.getDefaultFileName() - val fileExistsValue = FileIO.checkIfDifferentFile(fileName) - return if (FileIO.isCatrobatImage) { - val bitmapList = workspace.bitmapLisOfAllLayers - if (uri != null && fileExistsValue == Constants.IS_ORA) { - setUriToFormatUri(fileExistsValue) - OpenRasterFileFormatConversion.saveOraFileToUri(bitmapList, uri, fileName, bitmap, callback.contentResolver) - } else { - val imageUri = OpenRasterFileFormatConversion.exportToOraFile(bitmapList, fileName, bitmap, callback.contentResolver) - FileIO.currentFileNameOra = fileName - FileIO.uriFileOra = imageUri - imageUri - } - } else { - if (uri != null && FileIO.catroidFlag) { - FileIO.saveBitmapToUri(uri, callback.contentResolver, bitmap) - } else if (uri != null && fileExistsValue != Constants.IS_NO_FILE) { - setUriToFormatUri(fileExistsValue) - FileIO.saveBitmapToUri(uri, callback.contentResolver, bitmap) - } else { - val imageUri = FileIO.saveBitmapToFile(fileName, bitmap, callback.contentResolver) - if (FileIO.ending == ".png") { - FileIO.currentFileNamePng = fileName - FileIO.uriFilePng = imageUri - } else { - FileIO.currentFileNameJpg = fileName - FileIO.uriFileJpg = imageUri - } - imageUri - } - } - } catch (e: IOException) { - Log.d(TAG, "Can't save image file", e) - } catch (e: NullPointerException) { - Log.e(TAG, "Can't load image file", e) - } - } - return null - } - - private fun setUriToFormatUri(formatcode: Int) { - if (formatcode == Constants.IS_JPG) { - if (FileIO.uriFileJpg != null) { - uri = FileIO.uriFileJpg - } - } else if (formatcode == Constants.IS_PNG) { - if (FileIO.uriFilePng != null) { - uri = FileIO.uriFilePng - } - } else { - if (FileIO.uriFileOra != null) { - uri = FileIO.uriFileOra - } - } - } - - override fun onPostExecute(uri: Uri?) { - val callback = callbackRef.get() - if (callback != null && !callback.isFinishing) { - callback.onSaveImagePostExecute(requestCode, uri, saveAsCopy) - } - } - - interface SaveImageCallback { - fun onSaveImagePreExecute(requestCode: Int) - fun onSaveImagePostExecute(requestCode: Int, uri: Uri?, saveAsCopy: Boolean) - val contentResolver: ContentResolver? - val isFinishing: Boolean - } - - companion object { - private val TAG = SaveImageAsync::class.java.simpleName - } - - init { - this.uri = uri - this.saveAsCopy = saveAsCopy - this.workspace = workspace - } -} \ No newline at end of file diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/presenter/MainActivityPresenter.java b/Paintroid/src/main/java/org/catrobat/paintroid/presenter/MainActivityPresenter.java index bf585cf989..cae46c7a25 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/presenter/MainActivityPresenter.java +++ b/Paintroid/src/main/java/org/catrobat/paintroid/presenter/MainActivityPresenter.java @@ -64,9 +64,9 @@ import org.catrobat.paintroid.controller.ToolController; import org.catrobat.paintroid.dialog.PermissionInfoDialog; import org.catrobat.paintroid.iotasks.BitmapReturnValue; -import org.catrobat.paintroid.iotasks.CreateFileAsync.CreateFileCallback; +import org.catrobat.paintroid.iotasks.CreateFile.CreateFileCallback; import org.catrobat.paintroid.iotasks.LoadImageAsync.LoadImageCallback; -import org.catrobat.paintroid.iotasks.SaveImageAsync.SaveImageCallback; +import org.catrobat.paintroid.iotasks.SaveImage.SaveImageCallback; import org.catrobat.paintroid.tools.ToolType; import org.catrobat.paintroid.tools.Workspace; import org.catrobat.paintroid.ui.LayerAdapter; diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/ui/MainActivityInteractor.java b/Paintroid/src/main/java/org/catrobat/paintroid/ui/MainActivityInteractor.java deleted file mode 100644 index 92dfdf65c7..0000000000 --- a/Paintroid/src/main/java/org/catrobat/paintroid/ui/MainActivityInteractor.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Paintroid: An image manipulation application for Android. - * Copyright (C) 2010-2015 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.paintroid.ui; - -import android.content.Context; -import android.net.Uri; - -import org.catrobat.paintroid.contract.MainActivityContracts; -import org.catrobat.paintroid.iotasks.CreateFileAsync; -import org.catrobat.paintroid.iotasks.LoadImageAsync; -import org.catrobat.paintroid.iotasks.SaveImageAsync; -import org.catrobat.paintroid.tools.Workspace; - -public class MainActivityInteractor implements MainActivityContracts.Interactor { - - @Override - public void saveCopy(SaveImageAsync.SaveImageCallback callback, int requestCode, Workspace workspace) { - new SaveImageAsync(callback, requestCode, workspace, null, true).execute(); - } - - @Override - public void createFile(CreateFileAsync.CreateFileCallback callback, int requestCode, String filename) { - new CreateFileAsync(callback, requestCode, filename).execute(); - } - - @Override - public void saveImage(SaveImageAsync.SaveImageCallback callback, int requestCode, Workspace workspace, Uri uri) { - new SaveImageAsync(callback, requestCode, workspace, uri, false).execute(); - } - - @Override - public void loadFile(LoadImageAsync.LoadImageCallback callback, int requestCode, Uri uri, Context context, boolean scaling) { - new LoadImageAsync(callback, requestCode, uri, context, scaling).execute(); - } -} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/ui/MainActivityInteractor.kt b/Paintroid/src/main/java/org/catrobat/paintroid/ui/MainActivityInteractor.kt new file mode 100644 index 0000000000..eab5dab94c --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/ui/MainActivityInteractor.kt @@ -0,0 +1,63 @@ +/* + * Paintroid: An image manipulation application for Android. + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.paintroid.ui + +import android.content.Context +import android.net.Uri +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import org.catrobat.paintroid.contract.MainActivityContracts.Interactor +import org.catrobat.paintroid.iotasks.CreateFile +import org.catrobat.paintroid.iotasks.CreateFile.CreateFileCallback +import org.catrobat.paintroid.iotasks.LoadImageAsync +import org.catrobat.paintroid.iotasks.LoadImageAsync.LoadImageCallback +import org.catrobat.paintroid.iotasks.SaveImage +import org.catrobat.paintroid.iotasks.SaveImage.SaveImageCallback +import org.catrobat.paintroid.tools.Workspace + +class MainActivityInteractor : Interactor { + private val scopeIO = CoroutineScope(Dispatchers.IO) + + override fun saveCopy(callback: SaveImageCallback, requestCode: Int, workspace: Workspace) { + SaveImage(callback, requestCode, workspace, null, true, scopeIO).execute() + } + + override fun createFile(callback: CreateFileCallback, requestCode: Int, filename: String) { + CreateFile(callback, requestCode, filename, scopeIO).execute() + } + + override fun saveImage( + callback: SaveImageCallback, + requestCode: Int, + workspace: Workspace, + uri: Uri? + ) { + SaveImage(callback, requestCode, workspace, uri, false, scopeIO).execute() + } + + override fun loadFile( + callback: LoadImageCallback, + requestCode: Int, + uri: Uri?, + context: Context, + scaling: Boolean + ) { + LoadImageAsync(callback, requestCode, uri, context, scaling).execute() + } +} diff --git a/Paintroid/src/test/java/org/catrobat/paintroid/test/presenter/MainActivityPresenterTest.java b/Paintroid/src/test/java/org/catrobat/paintroid/test/presenter/MainActivityPresenterTest.java index c573c5f2ac..38c78e1dd2 100644 --- a/Paintroid/src/test/java/org/catrobat/paintroid/test/presenter/MainActivityPresenterTest.java +++ b/Paintroid/src/test/java/org/catrobat/paintroid/test/presenter/MainActivityPresenterTest.java @@ -41,7 +41,7 @@ import org.catrobat.paintroid.controller.ToolController; import org.catrobat.paintroid.dialog.PermissionInfoDialog; import org.catrobat.paintroid.iotasks.BitmapReturnValue; -import org.catrobat.paintroid.iotasks.SaveImageAsync; +import org.catrobat.paintroid.iotasks.SaveImage; import org.catrobat.paintroid.presenter.MainActivityPresenter; import org.catrobat.paintroid.tools.ToolType; import org.catrobat.paintroid.tools.Workspace; @@ -969,7 +969,7 @@ public void testHandlePermissionResultSavePermissionGranted() { Uri uri = model.getSavedPictureUri(); - verify(interactor).saveImage(any(SaveImageAsync.SaveImageCallback.class), eq(SAVE_IMAGE_DEFAULT), eq(workspace), eq(uri)); + verify(interactor).saveImage(any(SaveImage.SaveImageCallback.class), eq(SAVE_IMAGE_DEFAULT), eq(workspace), eq(uri)); } @Test @@ -1000,7 +1000,7 @@ public void testHandlePermissionResultSaveCopyPermissionGranted() { new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, new int[]{PackageManager.PERMISSION_GRANTED}); - verify(interactor).saveCopy(any(SaveImageAsync.SaveImageCallback.class), eq(SAVE_IMAGE_DEFAULT), eq(workspace)); + verify(interactor).saveCopy(any(SaveImage.SaveImageCallback.class), eq(SAVE_IMAGE_DEFAULT), eq(workspace)); } @Test