Remove unmaintained UI tests and remove deprecated AndroidJunit4 usage

This commit is contained in:
Julian Raufelder 2022-05-16 13:02:45 +02:00
parent 0ff8ac3cb5
commit c68e30e142
No known key found for this signature in database
GPG Key ID: 17EE71F6634E381D
25 changed files with 7 additions and 3170 deletions

View File

@ -100,6 +100,7 @@ ext {
rulesVersion = '1.4.0' rulesVersion = '1.4.0'
contributionVersion = '3.4.0' contributionVersion = '3.4.0'
uiautomatorVersion = '2.2.0' uiautomatorVersion = '2.2.0'
androidxTestJunitKtlnVersion = '1.1.3'
androidxCoreVersion = '1.6.0' androidxCoreVersion = '1.6.0'
androidxFragmentVersion = '1.3.6' androidxFragmentVersion = '1.3.6'
@ -126,6 +127,7 @@ ext {
documentFile : "androidx.documentfile:documentfile:${androidxDocumentfileVersion}", documentFile : "androidx.documentfile:documentfile:${androidxDocumentfileVersion}",
recyclerView : "androidx.recyclerview:recyclerview:${androidxRecyclerViewVersion}", recyclerView : "androidx.recyclerview:recyclerview:${androidxRecyclerViewVersion}",
androidxTestCore : "androidx.test:core:${androidxTestCoreVersion}", androidxTestCore : "androidx.test:core:${androidxTestCoreVersion}",
androidxTestJunitKtln : "androidx.test.ext:junit-ktx:${androidxTestJunitKtlnVersion}",
commonsCodec : "commons-codec:commons-codec:${commonsCodecVersion}", commonsCodec : "commons-codec:commons-codec:${commonsCodecVersion}",
cryptolib : "org.cryptomator:cryptolib:${cryptolibVersion}", cryptolib : "org.cryptomator:cryptolib:${cryptolibVersion}",
dagger : "com.google.dagger:dagger:${daggerVersion}", dagger : "com.google.dagger:dagger:${daggerVersion}",

View File

@ -191,6 +191,7 @@ dependencies {
testRuntimeOnly dependencies.junitEngine testRuntimeOnly dependencies.junitEngine
testImplementation dependencies.junitParams testImplementation dependencies.junitParams
testRuntimeOnly dependencies.junit4Engine testRuntimeOnly dependencies.junit4Engine
implementation dependencies.androidxTestJunitKtln
testImplementation dependencies.mockito testImplementation dependencies.mockito
testImplementation dependencies.mockitoKotlin testImplementation dependencies.mockitoKotlin

View File

@ -2,9 +2,10 @@ package org.cryptomator.data.db
import android.content.Context import android.content.Context
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import androidx.test.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.base.Optional
import org.cryptomator.data.db.entities.CloudEntityDao import org.cryptomator.data.db.entities.CloudEntityDao
import org.cryptomator.data.db.entities.UpdateCheckEntityDao import org.cryptomator.data.db.entities.UpdateCheckEntityDao
import org.cryptomator.data.db.entities.VaultEntityDao import org.cryptomator.data.db.entities.VaultEntityDao
@ -25,7 +26,7 @@ import org.junit.runner.RunWith
@SmallTest @SmallTest
class UpgradeDatabaseTest { class UpgradeDatabaseTest {
private val context = InstrumentationRegistry.getTargetContext() private val context = InstrumentationRegistry.getInstrumentation().context
private val sharedPreferencesHandler = SharedPreferencesHandler(context) private val sharedPreferencesHandler = SharedPreferencesHandler(context)
private lateinit var db: Database private lateinit var db: Database

View File

@ -1,422 +0,0 @@
package org.cryptomator.presentation;
import androidx.test.rule.ActivityTestRule;
import org.cryptomator.data.cloud.local.file.RootLocalFolder;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.CloudFile;
import org.cryptomator.domain.CloudFolder;
import org.cryptomator.domain.CloudNode;
import org.cryptomator.domain.CloudType;
import org.cryptomator.domain.LocalStorageCloud;
import org.cryptomator.domain.exception.BackendException;
import org.cryptomator.domain.exception.CloudNodeAlreadyExistsException;
import org.cryptomator.domain.repository.CloudContentRepository;
import org.cryptomator.domain.usecases.ProgressAware;
import org.cryptomator.domain.usecases.cloud.ByteArrayDataSource;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import org.cryptomator.presentation.testCloud.CryptoTestCloud;
import org.cryptomator.presentation.testCloud.DropboxTestCloud;
import org.cryptomator.presentation.testCloud.GoogledriveTestCloud;
import org.cryptomator.presentation.testCloud.LocalStorageTestCloud;
import org.cryptomator.presentation.testCloud.LocalTestCloud;
import org.cryptomator.presentation.testCloud.OnedriveTestCloud;
import org.cryptomator.presentation.testCloud.TestCloud;
import org.cryptomator.presentation.testCloud.WebdavTestCloud;
import org.cryptomator.presentation.ui.activity.SplashActivity;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static androidx.test.InstrumentationRegistry.getTargetContext;
import static org.cryptomator.presentation.CloudNodeMatchers.aFile;
import static org.cryptomator.presentation.CloudNodeMatchers.folder;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.collection.IsEmptyCollection.emptyCollectionOf;
@RunWith(Parameterized.class)
public class CloudContentRepositoryBlackboxTest {
private static final byte[] DIGITS_ONE_TO_TEN_AS_BYTES = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
private static final byte[] DIGITS_SEVEN_TO_ONE_AS_BYTES = new byte[] {7, 6, 5, 4, 3, 2, 1};
private static Cloud cloud;
private static TestCloud inTestCloud;
private static boolean setupCloudCompleted = false;
@Rule
public final ActivityTestRule<SplashActivity> activityTestRule = new ActivityTestRule<>(SplashActivity.class);
@Rule
public ExpectedException thrown = ExpectedException.none();
private CloudContentRepository inTest;
private CloudFolder root;
public CloudContentRepositoryBlackboxTest(TestCloud testCloud) {
if (inTestCloud != null && inTestCloud != testCloud) {
setupCloudCompleted = false;
}
inTestCloud = testCloud;
}
@Parameterized.Parameters(name = "{0}")
public static TestCloud[] data() {
return new TestCloud[] { //
new LocalStorageTestCloud(), //
new LocalTestCloud(), //
new WebdavTestCloud(getTargetContext()), //
new DropboxTestCloud(getTargetContext()), //
new GoogledriveTestCloud(), //
new OnedriveTestCloud(getTargetContext()), //
new CryptoTestCloud()};
}
@Before
public void setup() throws BackendException {
ApplicationComponent appComponent = ((CryptomatorApp) activityTestRule //
.getActivity() //
.getApplication()) //
.getComponent();
if (!setupCloudCompleted) {
if (inTestCloud instanceof CryptoTestCloud) {
// FIXME 343 @julian just for testcase local cloud
Cloud testCloud = appComponent.cloudRepository().clouds(CloudType.LOCAL).get(0);
CloudFolder rootFolder = new RootLocalFolder((LocalStorageCloud) testCloud);
cloud = ((CryptoTestCloud) inTestCloud).getInstance(appComponent, testCloud, rootFolder);
} else {
cloud = inTestCloud.getInstance(appComponent);
}
setupCloudCompleted = true;
}
inTest = appComponent.cloudContentRepository();
root = inTest.create(inTest.resolve(cloud, UUID.randomUUID().toString()));
}
@Test
public void testListEmptyDirectory() throws BackendException {
assertThat(listingOf(root), is(emptyCollectionOf(CloudNode.class)));
}
@Test
public void testListDirectory() throws BackendException {
createParentsAndWrite("a", DIGITS_SEVEN_TO_ONE_AS_BYTES);
createParentsAndWrite("b.dat", DIGITS_ONE_TO_TEN_AS_BYTES);
createParentsAndWrite("empty.txt", new byte[0]);
inTest.create(inTest.folder(root, "b"));
inTest.create(inTest.folder(root, "c"));
assertThat(listingOf(root), containsInAnyOrder( //
aFile().withName("a").withSize(DIGITS_SEVEN_TO_ONE_AS_BYTES.length), //
aFile().withName("b.dat").withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length), //
aFile().withName("empty.txt").withSize(0L), //
folder("b"), //
folder("c")));
}
@Test
public void testCreateDirectory() throws BackendException {
CloudFolder created = inTest.folder(root, "created");
created = inTest.create(created);
assertThat(listingOf(created), is(emptyCollectionOf(CloudNode.class)));
assertThat(listingOf(root), containsInAnyOrder(folder("created")));
}
@Test
public void testDeleteDirectory() throws BackendException {
inTest.create(inTest.folder(root, "created"));
inTest.delete(inTest.folder(root, "created"));
assertThat(inTest.exists(inTest.folder(root, "created")), is(false));
assertThat(listingOf(root), is(emptyCollectionOf(CloudNode.class)));
}
@Test
@SuppressWarnings("deprecation")
public void testUploadFile() throws BackendException {
Date start = new Date();
CloudFile file = createParentsAndWrite("file", DIGITS_ONE_TO_TEN_AS_BYTES);
assertThat(file, is(aFile() //
.withName("file") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length) //
.withModifiedIn(start, new Date())));
assertThat(listingOf(root), //
containsInAnyOrder(aFile() //
.withName("file") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
}
@Test
@SuppressWarnings("deprecation")
public void testReplaceFile() throws BackendException {
createParentsAndWrite("file", DIGITS_ONE_TO_TEN_AS_BYTES);
Date start = new Date();
CloudFile file = createParentsAndWriteOrReplace("file", DIGITS_SEVEN_TO_ONE_AS_BYTES);
assertThat(file, is(aFile() //
.withName("file") //
.withSize(DIGITS_SEVEN_TO_ONE_AS_BYTES.length) //
.withModifiedIn(start, new Date())));
assertThat(listingOf(root), //
containsInAnyOrder(aFile() //
.withName("file") //
.withSize(DIGITS_SEVEN_TO_ONE_AS_BYTES.length)));
}
@Test
public void testUploadExistingFileWithoutReplaceFlag() throws BackendException {
createParentsAndWrite("file", DIGITS_ONE_TO_TEN_AS_BYTES);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("CloudNode already exists and replace is false");
createParentsAndWrite("file", DIGITS_ONE_TO_TEN_AS_BYTES);
}
@Test
public void testDownloadFile() throws BackendException {
createParentsAndWrite("file", DIGITS_ONE_TO_TEN_AS_BYTES);
assertThat(read(inTest.file(root, "file")), is(DIGITS_ONE_TO_TEN_AS_BYTES));
}
@Test
public void testDeleteFile() throws BackendException {
createParentsAndWrite("file", DIGITS_ONE_TO_TEN_AS_BYTES);
inTest.delete(inTest.file(root, "file"));
assertThat(inTest.exists(inTest.file(root, "file")), is(false));
assertThat(listingOf(root), is(emptyCollectionOf(CloudNode.class)));
}
@Test
@SuppressWarnings("deprecation")
public void testRenameDirectory() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder target = inTest.folder(root, "newName");
target = inTest.move(directory, target);
assertThat(listingOf(target), containsInAnyOrder(aFile() //
.withName("file") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
}
@Test
public void testRenameDirectoryToExistingDirectory() throws BackendException {
CloudFolder directory = inTest.folder(root, "directory");
directory = inTest.create(directory);
CloudFolder target = inTest.folder(root, "newName");
target = inTest.create(target);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("newName");
inTest.move(directory, target);
}
@Test
@SuppressWarnings("deprecation")
public void testRenameDirectoryToExistingFile() throws BackendException {
CloudFolder directory = inTest.folder(root, "directory");
directory = inTest.create(directory);
CloudFolder target = inTest.folder(root, "newName");
createParentsAndWrite("newName", new byte[0]);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("newName");
inTest.move(directory, target);
}
@Test
@SuppressWarnings("deprecation")
public void testMoveDirectory() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFolder target = inTest.folder(newParent, "directory");
target = inTest.move(directory, target);
assertThat(listingOf(target), containsInAnyOrder(aFile() //
.withName("file") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
}
@Test
@SuppressWarnings("deprecation")
public void testMoveDirectoryToExistingDirectory() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFolder target = inTest.folder(newParent, "directory");
target = inTest.create(target);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("directory");
inTest.move(directory, target);
}
@Test
@SuppressWarnings("deprecation")
public void testMoveDirectoryToExistingFile() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFolder target = inTest.folder(newParent, "directory");
createParentsAndWrite("newParent/directory", new byte[0]);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("directory");
inTest.move(directory, target);
}
@Test
@SuppressWarnings("deprecation")
public void testMoveAndRenameDirectory() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFolder target = inTest.folder(newParent, "newName");
target = inTest.move(directory, target);
assertThat(listingOf(target), containsInAnyOrder(aFile() //
.withName("file") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
}
@Test
@SuppressWarnings("deprecation")
public void testMoveAndRenameDirectoryToExistingDirectory() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFolder target = inTest.folder(newParent, "newName");
target = inTest.create(target);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("newName");
inTest.move(directory, target);
}
@Test
@SuppressWarnings("deprecation")
public void testMoveAndRenameDirectoryToExistingFile() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder directory = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFolder target = inTest.folder(newParent, "newName");
createParentsAndWrite("newParent/newName", new byte[0]);
thrown.expect(CloudNodeAlreadyExistsException.class);
thrown.expectMessage("newName");
inTest.move(directory, target);
}
@Test
@SuppressWarnings("deprecation")
public void testRenameFile() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFile target = inTest.file(file.getParent(), "newName");
target = inTest.move(file, target);
assertThat(listingOf(file.getParent()), containsInAnyOrder(aFile() //
.withName("newName") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
assertThat(read(target), is(DIGITS_ONE_TO_TEN_AS_BYTES));
}
@Test
@SuppressWarnings("deprecation")
public void testMoveFile() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder oldParent = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFile target = inTest.file(newParent, "file");
target = inTest.move(file, target);
assertThat(listingOf(oldParent), is(emptyCollectionOf(CloudNode.class)));
assertThat(listingOf(newParent), containsInAnyOrder(aFile() //
.withName("file") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
assertThat(read(target), is(DIGITS_ONE_TO_TEN_AS_BYTES));
}
@Test
@SuppressWarnings("deprecation")
public void testMoveAndRenameFile() throws BackendException {
CloudFile file = createParentsAndWrite("directory/file", DIGITS_ONE_TO_TEN_AS_BYTES);
CloudFolder oldParent = file.getParent();
CloudFolder newParent = inTest.create(inTest.folder(root, "newParent"));
CloudFile target = inTest.file(newParent, "newName");
target = inTest.move(file, target);
assertThat(listingOf(oldParent), is(emptyCollectionOf(CloudNode.class)));
assertThat(listingOf(newParent), containsInAnyOrder(aFile() //
.withName("newName") //
.withSize(DIGITS_ONE_TO_TEN_AS_BYTES.length)));
assertThat(read(target), is(DIGITS_ONE_TO_TEN_AS_BYTES));
}
@After
public void teardown() throws BackendException {
if (inTest != null && root != null) {
inTest.delete(root);
}
}
private List<CloudNode> listingOf(CloudFolder testRoot) throws BackendException {
return inTest.list(testRoot);
}
private byte[] read(CloudFile file) throws BackendException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
inTest.read(file, null, out, ProgressAware.NO_OP_PROGRESS_AWARE_DOWNLOAD);
return out.toByteArray();
}
private CloudFile createParentsAndWrite(String path, byte[] data) throws BackendException {
return createParentsAndWriteOrReplaceImpl(path, data, false);
}
private CloudFile createParentsAndWriteOrReplace(String path, byte[] data) throws BackendException {
return createParentsAndWriteOrReplaceImpl(path, data, true);
}
private CloudFile createParentsAndWriteOrReplaceImpl(String path, byte[] data, boolean repalce) throws BackendException {
path = root.getName() + "/" + path;
String pathToParent = path.substring(0, path.lastIndexOf('/') + 1);
String name = path.substring(path.lastIndexOf('/') + 1);
CloudFolder parent = inTest.resolve(cloud, pathToParent);
if (!inTest.exists(parent)) {
parent = inTest.create(parent);
}
CloudFile file = inTest.file(parent, name, new Long(data.length));
return inTest.write(file, ByteArrayDataSource.from(data), ProgressAware.NO_OP_PROGRESS_AWARE_UPLOAD, repalce, data.length);
}
}

View File

@ -1,126 +0,0 @@
package org.cryptomator.presentation;
import org.cryptomator.domain.CloudFile;
import org.cryptomator.domain.CloudFolder;
import org.cryptomator.domain.CloudNode;
import com.google.common.base.Optional;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import java.util.Date;
class CloudNodeMatchers {
public static Matcher<CloudNode> aFile(final String name) {
return (Matcher) new TypeSafeDiagnosingMatcher<CloudFile>() {
@Override
protected boolean matchesSafely(CloudFile file, Description description) {
if (name.equals(file.getName())) {
return true;
} else {
description.appendText("aFile with name '").appendText(file.getName()).appendText("'");
return false;
}
}
@Override
public void describeTo(Description description) {
description.appendText("aFile with name '").appendText(name).appendText("'");
}
};
}
public static FileMatcher aFile() {
return new FileMatcher();
}
public static Matcher<CloudNode> folder(final String name) {
return (Matcher) new TypeSafeDiagnosingMatcher<CloudFolder>() {
@Override
protected boolean matchesSafely(CloudFolder file, org.hamcrest.Description description) {
if (name.equals(file.getName())) {
return true;
} else {
description.appendText("folder with name '").appendText(file.getName()).appendText("'");
return false;
}
}
@Override
public void describeTo(org.hamcrest.Description description) {
description.appendText("folder with name '").appendText(name).appendText("'");
}
};
}
public static class FileMatcher extends TypeSafeDiagnosingMatcher<CloudNode> {
private String nameToCheck;
private Optional<Long> sizeToCheck;
private Date minModifiedToCheck;
private Date maxModifiedToCheck;
private FileMatcher() {
super(CloudFile.class);
}
public FileMatcher withName(String name) {
this.nameToCheck = name;
return this;
}
public FileMatcher withSize(int size) {
return withSize(Long.valueOf(size));
}
public FileMatcher withSize(Long size) {
this.sizeToCheck = Optional.ofNullable(size);
return this;
}
public FileMatcher withModifiedIn(Date minModified, Date maxModified) {
this.minModifiedToCheck = minModified;
this.maxModifiedToCheck = maxModified;
return this;
}
@Override
public void describeTo(Description description) {
description.appendText("a file");
if (nameToCheck != null) {
description.appendText(" with name ").appendText(nameToCheck);
}
if (sizeToCheck != null) {
description.appendText(" with size ").appendValue(sizeToCheck);
}
if (minModifiedToCheck != null) {
description.appendText(" with modified in [").appendValue(minModifiedToCheck).appendText(",").appendValue(maxModifiedToCheck).appendText("]");
}
}
@Override
protected boolean matchesSafely(CloudNode cloudNode, Description description) {
CloudFile cloudFile = (CloudFile) cloudNode;
boolean match = true;
description.appendText("a file");
if (nameToCheck != null && !nameToCheck.equals(cloudFile.getName())) {
description.appendText(" with name ").appendText(cloudFile.getName());
match = false;
}
if (sizeToCheck != null && !sizeToCheck.equals(cloudFile.getSize())) {
description.appendText(" with size ").appendValue(cloudFile.getSize());
match = false;
}
if (minModifiedToCheck != null && dateInRange(minModifiedToCheck, maxModifiedToCheck, cloudFile.getModified())) {
description.appendText(" with modified ").appendValue(cloudFile.getModified());
}
return match;
}
private boolean dateInRange(Date min, Date max, Optional<Date> modified) {
return modified.isPresent() && !modified.get().before(min) && !modified.get().after(max);
}
}
}

View File

@ -1,71 +0,0 @@
package org.cryptomator.presentation.testCloud;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.CloudFolder;
import org.cryptomator.domain.Vault;
import org.cryptomator.domain.exception.BackendException;
import org.cryptomator.domain.exception.FatalBackendException;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import static org.cryptomator.domain.Vault.aVault;
public class CryptoTestCloud extends TestCloud {
private final static String VAULT_PASSWORD = "password";
private final static String VAULT_NAME = "testVault";
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
throw new IllegalStateException();
}
public Cloud getInstance(ApplicationComponent appComponent, Cloud testCloud, CloudFolder rootFolder) {
try {
CloudFolder vaultFolder = appComponent //
.cloudContentRepository() //
.folder(rootFolder, VAULT_NAME);
Vault vault = aVault() //
.thatIsNew() //
.withCloud(testCloud) //
.withNamePathAndCloudFrom(vaultFolder) //
.build();
cleanup(appComponent, vault, vaultFolder);
vaultFolder = appComponent.cloudContentRepository().create(vaultFolder);
appComponent.cloudRepository().create(vaultFolder, VAULT_PASSWORD);
vault = appComponent.vaultRepository().store(vault);
return appComponent.cloudRepository().unlock(vault, VAULT_PASSWORD, () -> false);
} catch (BackendException e) {
throw new AssertionError(e);
}
}
private void cleanup(ApplicationComponent appComponent, Vault vault, CloudFolder vaultFolder) {
try {
appComponent.cloudContentRepository().delete(vaultFolder);
} catch (BackendException | FatalBackendException e) {
}
try {
appComponent.vaultRepository().vaults().forEach(vaultInRepo -> {
if (vaultInRepo.getName().equals(vault.getName()) //
&& vaultInRepo.getPath().equals(vault.getPath())) {
try {
appComponent.vaultRepository().delete(vaultInRepo);
} catch (BackendException e) {
throw new AssertionError(e);
}
}
});
} catch (FatalBackendException | BackendException e) {
}
}
@Override
public String toString() {
return "CryptoTestCloud";
}
}

View File

@ -1,31 +0,0 @@
package org.cryptomator.presentation.testCloud;
import android.content.Context;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.WebDavCloud;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import org.cryptomator.util.crypto.CredentialCryptor;
public class DropboxTestCloud extends TestCloud {
private final Context context;
public DropboxTestCloud(Context context) {
this.context = context;
}
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
return WebDavCloud.aWebDavCloudCloud() //
.withUrl("https://webdav.mc.gmx.net") //
.withUsername("jraufelder@gmx.de") //
.withPassword(CredentialCryptor.getInstance(context).encrypt("mG7!3B3Mx")) //
.build();
}
@Override
public String toString() {
return "DropboxTestCloud";
}
}

View File

@ -1,86 +0,0 @@
package org.cryptomator.presentation.testCloud;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import junit.framework.AssertionFailedError;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.GoogleDriveCloud;
import org.cryptomator.presentation.R;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.cryptomator.presentation.ui.TestUtil.GOOGLE_DRIVE;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.withRecyclerView;
import static org.cryptomator.presentation.ui.activity.CloudsOperationsTest.checkLoginResult;
import static org.cryptomator.presentation.ui.activity.CloudsOperationsTest.openCloudServices;
public class GoogledriveTestCloud extends TestCloud {
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
login();
return GoogleDriveCloud.aGoogleDriveCloud() //
.withUsername("geselthyn@googlemail.com") //
.withAccessToken("geselthyn@googlemail.com") //
.build();
}
public void login() {
UiDevice device = UiDevice.getInstance(getInstrumentation());
openCloudServices(device);
if (alreadyLoggedIn()) {
return;
}
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(GOOGLE_DRIVE, click()));
try {
device //
.findObject(new UiSelector().resourceId("android:id/text1")) //
.click();
device //
.findObject(new UiSelector().resourceId("android:id/button1")) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("GoogleDrive login failed");
}
device.waitForIdle();
checkLoginResult("Google Drive", GOOGLE_DRIVE);
}
private boolean alreadyLoggedIn() {
try {
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(GOOGLE_DRIVE, R.id.tv_cloud_name)) //
.check(matches(withText(InstrumentationRegistry //
.getTargetContext() //
.getString(R.string.screen_cloud_settings_sign_out_from_cloud) + " Google Drive")));
} catch (AssertionFailedError e) {
return false;
}
return true;
}
@Override
public String toString() {
return "GoogledriveTestCloud";
}
}

View File

@ -1,63 +0,0 @@
package org.cryptomator.presentation.testCloud;
import androidx.test.uiautomator.UiDevice;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.CloudType;
import org.cryptomator.domain.LocalStorageCloud;
import org.cryptomator.domain.exception.BackendException;
import org.cryptomator.presentation.R;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.TestUtil.LOCAL;
import static org.cryptomator.presentation.ui.TestUtil.chooseSdCard;
import static org.cryptomator.presentation.ui.activity.CloudsOperationsTest.openCloudServices;
import static org.cryptomator.presentation.ui.activity.LoginLocalClouds.chooseFolder;
public class LocalStorageTestCloud extends TestCloud {
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
login();
try {
return appComponent.cloudRepository() //
.clouds(CloudType.LOCAL).stream() //
.map(LocalStorageCloud.class::cast) //
.filter(cloud -> cloud.rootUri() != null) //
.findFirst() //
.get();
} catch (BackendException e) {
throw new RuntimeException(e);
}
}
private void login() {
UiDevice device = UiDevice.getInstance(getInstrumentation());
openCloudServices(device);
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(LOCAL, click()));
awaitCompleted();
onView(withId(R.id.floating_action_button)) //
.perform(click());
awaitCompleted();
chooseSdCard(device);
awaitCompleted();
chooseFolder(device);
}
@Override
public String toString() {
return "LocalStorageTestCloud";
}
}

View File

@ -1,28 +0,0 @@
package org.cryptomator.presentation.testCloud;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.LocalStorageCloud;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
public class LocalTestCloud extends TestCloud {
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
getInstrumentation() //
.getUiAutomation() //
.executeShellCommand("pm grant " + "org.cryptomator" + " android.permission.READ_EXTERNAL_STORAGE");
getInstrumentation() //
.getUiAutomation() //
.executeShellCommand("pm grant " + "org.cryptomator" + " android.permission.WRITE_EXTERNAL_STORAGE");
return LocalStorageCloud.aLocalStorage().build();
}
@Override
public String toString() {
return "LocalTestCloud";
}
}

View File

@ -1,46 +0,0 @@
package org.cryptomator.presentation.testCloud;
import android.content.Context;
import android.content.SharedPreferences;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.OnedriveCloud;
import org.cryptomator.presentation.di.component.ApplicationComponent;
public class OnedriveTestCloud extends TestCloud {
private final Context context;
public OnedriveTestCloud(Context context) {
this.context = context;
}
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
SharedPreferences sharedPreferences = context.getSharedPreferences("com.microsoft.live", 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("refresh_token", "OAQABAAAAAABHh4kmS_aKT5XrjzxRAtHzMkxzFfIzutF8Q04IwuU77Vmp5-ErO6muS0-watCiLjvPG" + //
"-QICK6PwzSsJZApKZPIyTgDxJuElkhM9j9Caa-NGXKx3JPZx4Tk5X3zhmSWebZdQu2TM1N" + //
"RrKWLl2k2m3Zj7xr1zEsjcr4tUjjrZl_W6EIglAIoi-DPOwznIEDWAzWCJeUY76CIpywax" + //
"RTsbcZXD3u2321kIGaL-bnGLa_z5IzUbal0PcYfPNYPXXTuv8eMyl4L9Tls1tSEseTHgCu" + //
"X3OZU2owiGQk6ycDAeyrbRaPoUOA78GYuaJGUXRmhAeH1WBccUzABdrZmAY1dAt4yu2eV7" + //
"70RzrDQhbLCPV3u3x-7xEtvsM8w0W7096VBuu2-MXvaWuDccnCHo_PK8ketpow19_llBI9" + //
"fx7yBnIU-HCkKuvOCKcvVq3Bv9r312bwAoWHdOrxsKrNK8aLoR317O9Cxjpr7q-YI3NSJJ" + //
"veTK_vn2uE0e6gppGOYSmpJIvoW82ZVngpptW0jsp6rOsnkSg2yfKKpIPN-n0U1njVlYf8" + //
"cwsS99tx8NDdCPS6MTkVmcdKRJ4dhMuuWdEm4E_hZRnnj2Pya3APxjL2eqyAR1-54TDLF-" + //
"-L-jIJUS4bVpC_RBQn4fxcrX4s-ddo6I0ejfdC07mU_Np9p66VJ_3_Yokt64fFw-zzaGpn" + //
"QEzRMxtJp5G40MAelYwxLhDIc-syw91JEoSSqfGJYHETKExPlnQOw-rqLGPFbIF6OKFNqO" + //
"XtVLWKZFxIEf-EFQbhq5igZz8DZ2n-cRxC3HWi_x18tVSAA");
editor.commit();
return OnedriveCloud.aOnedriveCloud() //
.withUsername("info@cryptomator.org") //
.withAccessToken("authenticated") //
.build();
}
@Override
public String toString() {
return "OnedriveTestCloud";
}
}

View File

@ -1,9 +0,0 @@
package org.cryptomator.presentation.testCloud;
import org.cryptomator.domain.Cloud;
import org.cryptomator.presentation.di.component.ApplicationComponent;
public abstract class TestCloud {
public abstract Cloud getInstance(ApplicationComponent appComponent);
}

View File

@ -1,31 +0,0 @@
package org.cryptomator.presentation.testCloud;
import android.content.Context;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.WebDavCloud;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import org.cryptomator.util.crypto.CredentialCryptor;
public class WebdavTestCloud extends TestCloud {
private final Context context;
public WebdavTestCloud(Context context) {
this.context = context;
}
@Override
public Cloud getInstance(ApplicationComponent appComponent) {
return WebDavCloud.aWebDavCloudCloud() //
.withUrl("https://webdav.mc.gmx.net") //
.withUsername("jraufelder@gmx.de") //
.withPassword(CredentialCryptor.getInstance(context).encrypt("mG7!3B3Mx")) //
.build();
}
@Override
public String toString() {
return "WebdavTestCloud";
}
}

View File

@ -1,65 +0,0 @@
package org.cryptomator.presentation.ui;
import android.content.res.Resources;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
/**
* Created by dannyroa on 5/10/15.
*/
public class RecyclerViewMatcher {
private final int recyclerViewId;
public RecyclerViewMatcher(int recyclerViewId) {
this.recyclerViewId = recyclerViewId;
}
public Matcher<View> atPositionOnView(final int position, final int targetViewId) {
return new TypeSafeMatcher<View>() {
Resources resources = null;
View childView;
public void describeTo(Description description) {
String idDescription = Integer.toString(recyclerViewId);
if (this.resources != null) {
try {
idDescription = this.resources.getResourceName(recyclerViewId);
} catch (Resources.NotFoundException var4) {
idDescription = String.format("%s (resource name not found)", recyclerViewId);
}
}
description.appendText("with id: " + idDescription);
}
public boolean matchesSafely(View view) {
this.resources = view.getResources();
if (childView == null) {
RecyclerView recyclerView = view.getRootView().findViewById(recyclerViewId);
if (recyclerView != null && recyclerView.getId() == recyclerViewId) {
childView = recyclerView.findViewHolderForAdapterPosition(position).itemView;
} else {
return false;
}
}
if (targetViewId == -1) {
return view == childView;
} else {
View targetView = childView.findViewById(targetViewId);
return view == targetView;
}
}
};
}
}

View File

@ -1,179 +0,0 @@
package org.cryptomator.presentation.ui;
import androidx.test.espresso.ViewInteraction;
import androidx.test.rule.ActivityTestRule;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import org.cryptomator.domain.Cloud;
import org.cryptomator.domain.CloudFolder;
import org.cryptomator.domain.CloudNode;
import org.cryptomator.domain.CloudType;
import org.cryptomator.domain.Vault;
import org.cryptomator.domain.exception.BackendException;
import org.cryptomator.presentation.R;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import org.hamcrest.Matchers;
import java.util.List;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.RootMatchers.withDecorView;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.core.Is.is;
public class TestUtil {
public static final int DROPBOX = 0;
public static final int GOOGLE_DRIVE = 1;
public static final int ONEDRIVE = 2;
public static final int WEBDAV = 3;
public static final int LOCAL = 4;
private static final String SD_CARD_REGEX = "(?i)SD[- ]*(CARD|KARTE)";
public static void isToastDisplayed(String message, ActivityTestRule activityTestRule) {
onView(withText(message)) //
.inRoot(withDecorView(not(is(activityTestRule.getActivity().getWindow().getDecorView())))) //
.check(matches(isDisplayed()));
}
public static void openMenu(UiDevice device) {
try {
final UiSelector toolbar = new UiSelector() //
.resourceId("com.android.documentsui:id/toolbar");
device //
.findObject(toolbar.childSelector(new UiSelector().index(0))) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Menu not found");
}
}
public static void chooseSdCard(UiDevice device) {
try {
if (!sdCardAlreadySelected()) {
openMenu(device);
device //
.findObject(new UiSelector().textMatches(SD_CARD_REGEX)) //
.click();
}
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Menu not found");
}
}
private static boolean sdCardAlreadySelected() {
ViewInteraction textView = onView(allOf(withText("SDCARD"), withParent(withId(R.id.toolbar)), isDisplayed()));
return textView.check(matches(withText("SDCARD"))) != null;
}
public static void openSettings(UiDevice device) {
awaitCompleted();
waitForIdle(device);
openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
waitForIdle(device);
onView(allOf( //
withId(R.id.title), //
withText(R.string.snack_bar_action_title_settings))) //
.perform(click());
awaitCompleted();
}
public static void waitForIdle(UiDevice uiDevice) {
uiDevice.waitForIdle();
}
public static void addFolderInCloud(ApplicationComponent appComponent, String path, CloudType cloudType) {
try {
CloudFolder vaultFolder = (CloudFolder) getNode(appComponent, getEncryptedCloud(appComponent, cloudType), path);
if (!appComponent.cloudContentRepository().exists(vaultFolder)) {
assertThat(appComponent.cloudContentRepository().create(vaultFolder), Matchers.is(notNullValue()));
}
} catch (BackendException e) {
throw new AssertionError("Error while adding testVault");
}
}
public static void removeFolderInCloud(ApplicationComponent appComponent, String path, CloudType cloudType) {
try {
CloudFolder vaultFolder = (CloudFolder) getNode(appComponent, getEncryptedCloud(appComponent, cloudType), path);
if (appComponent.cloudContentRepository().exists(vaultFolder)) {
appComponent.cloudContentRepository().delete(vaultFolder);
}
} catch (BackendException e) {
throw new AssertionError("Error while removing testVault");
}
}
private static Cloud getEncryptedCloud(ApplicationComponent appComponent, CloudType cloudType) throws BackendException {
Cloud cloud;
if (cloudType.equals(CloudType.LOCAL)) {
cloud = appComponent.cloudRepository().clouds(cloudType).get(1);
} else {
cloud = appComponent.cloudRepository().clouds(cloudType).get(0);
}
return cloud;
}
private static CloudNode getNode(ApplicationComponent appComponent, Cloud cloud, String path) throws BackendException {
return appComponent.cloudContentRepository().resolve(cloud, path);
}
public static void removeFolderInVault(ApplicationComponent appComponent, String name, CloudType cloudType) {
try {
Cloud decryptedCloud = getDecryptedCloud(appComponent, cloudType);
CloudFolder root = appComponent.cloudContentRepository().root(decryptedCloud);
CloudFolder folder = appComponent.cloudContentRepository().folder(root, name);
appComponent.cloudContentRepository().delete(folder);
} catch (BackendException e) {
throw new AssertionError(e);
}
}
public static void addFolderInVaultsRoot(ApplicationComponent appComponent, String name, CloudType cloudType) {
try {
Cloud decryptedCloud = getDecryptedCloud(appComponent, cloudType);
CloudFolder root = appComponent.cloudContentRepository().root(decryptedCloud);
CloudFolder folder = appComponent.cloudContentRepository().folder(root, name);
assertThat(appComponent.cloudContentRepository().create(folder), is(notNullValue()));
} catch (BackendException e) {
throw new AssertionError(e);
}
}
private static Cloud getDecryptedCloud(ApplicationComponent appComponent, CloudType cloudType) throws BackendException {
List<Vault> vaults = appComponent.vaultRepository().vaults();
for (Vault vault : vaults) {
if (vault.getCloudType().equals(cloudType)) {
return appComponent.cloudRepository().decryptedViewOf(vault);
}
}
throw new AssertionError("Cloud for vault not found");
}
}

View File

@ -1,57 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import org.cryptomator.presentation.R;
import org.cryptomator.presentation.ui.RecyclerViewMatcher;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static java.lang.String.format;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.hamcrest.Matchers.allOf;
public class BasicNodeOperationsUtil {
static void openSettings(UiDevice device, int nodePosition) {
awaitCompleted();
waitForIdle(device);
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(nodePosition, R.id.settings)) //
.perform(click());
awaitCompleted();
}
static void waitForIdle(UiDevice uiDevice) {
uiDevice.waitForIdle();
}
static void checkEmptyFolderHint() {
awaitCompleted();
onView(allOf( //
withId(R.id.tv_empty_folder_hint), //
withText(R.string.screen_file_browser_msg_empty_folder))) //
.check(matches(withText(R.string.screen_file_browser_msg_empty_folder)));
}
static void checkFileOrFolderAlreadyExistsErrorMessage(String nodeName) {
onView(withId(R.id.tv_error)) //
.check(matches(withText(format( //
InstrumentationRegistry //
.getTargetContext() //
.getString(R.string.error_file_or_folder_exists), //
nodeName))));
}
public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) {
return new RecyclerViewMatcher(recyclerViewId);
}
}

View File

@ -1,248 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.ViewInteraction;
import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.rule.ActivityTestRule;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
import org.cryptomator.presentation.R;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.withChild;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static java.lang.Thread.sleep;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.TestUtil.DROPBOX;
import static org.cryptomator.presentation.ui.TestUtil.GOOGLE_DRIVE;
import static org.cryptomator.presentation.ui.TestUtil.LOCAL;
import static org.cryptomator.presentation.ui.TestUtil.ONEDRIVE;
import static org.cryptomator.presentation.ui.TestUtil.WEBDAV;
import static org.cryptomator.presentation.ui.TestUtil.openSettings;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.withRecyclerView;
import static org.hamcrest.core.AllOf.allOf;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CloudsOperationsTest {
private final UiDevice device = UiDevice.getInstance(getInstrumentation());
@Rule
public ActivityTestRule<SplashActivity> activityTestRule //
= new ActivityTestRule<>(SplashActivity.class);
public static void openCloudServices(UiDevice device) {
openSettings(device);
ViewInteraction recyclerView = onView(allOf(withId(R.id.recycler_view), childAtPosition(withId(android.R.id.list_container), 0)));
recyclerView.perform(RecyclerViewActions.actionOnItemAtPosition(3, click()));
awaitCompleted();
}
public static void checkLoginResult(String cloudName, int cloudPosition) {
String displayText = InstrumentationRegistry //
.getTargetContext() //
.getString(R.string.screen_cloud_settings_sign_out_from_cloud) + " " + cloudName;
UiObject signOutText = UiDevice.getInstance(getInstrumentation()).findObject(new UiSelector().text(displayText));
signOutText.waitForExists(15000);
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(cloudPosition, R.id.cloudName)) //
.check(matches(withText(displayText)));
}
private static Matcher<View> childAtPosition(final Matcher<View> parentMatcher, final int position) {
return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("Child at position " + position + " in parent ");
parentMatcher.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
ViewParent parent = view.getParent();
return parent instanceof ViewGroup && parentMatcher.matches(parent) //
&& view.equals(((ViewGroup) parent).getChildAt(position));
}
};
}
@Test
public void test01EnableDebugModeLeadsToDebugMode() {
openSettings(device);
try {
new UiScrollable(new UiSelector().scrollable(true)).scrollToEnd(10);
awaitCompleted();
onView(withChild(withText(R.string.screen_settings_debug_mode_label))) //
.perform(click());
awaitCompleted();
onView(withId(android.R.id.button1)) //
.perform(click());
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Scrolling down failed");
}
}
@Test
public void test02LoginDropboxCloudLeadsToLoggedInDropboxCloud() {
openCloudServices(device);
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(DROPBOX, click()));
try {
device //
.findObject(new UiSelector().resourceId("android:id/button_once")) //
.click();
device.waitForIdle();
device //
.findObject(new UiSelector().text("Email")) //
.setText("");
device //
.findObject(new UiSelector().text("Password")) //
.setText("");
device //
.findObject(new UiSelector().description("Sign in")) //
.click();
device.waitForIdle();
device //
.findObject(new UiSelector().description("Allow")) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Dropbox login failed");
}
device.waitForIdle();
checkLoginResult("Dropbox", DROPBOX);
}
@Test
public void test03LoginGoogleDriveCloudLeadsToLoggedInGoogleDriveCloud() {
openCloudServices(device);
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(GOOGLE_DRIVE, click()));
try {
device //
.findObject(new UiSelector().resourceId("android:id/text1")) //
.click();
device //
.findObject(new UiSelector().resourceId("android:id/button1")) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("GoogleDrive login failed");
}
device.waitForIdle();
checkLoginResult("Google Drive", GOOGLE_DRIVE);
}
@Test
public void test04LoginOneDriveLeadsToLoggedInOneDriveCloud() {
openCloudServices(device);
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(ONEDRIVE, click()));
try {
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
device //
.findObject(new UiSelector().resourceId("i0116")) //
.setText("");
device //
.findObject(new UiSelector().resourceId("idSIButton9")) //
.click();
device.waitForWindowUpdate(null, 500);
device //
.findObject(new UiSelector().resourceId("i0118")) //
.setText("");
device.waitForWindowUpdate(null, 500);
device //
.findObject(new UiSelector().resourceId("idSIButton9")) //
.click();
try {
device //
.findObject(new UiSelector().resourceId("idSIButton9")) //
.click();
} catch (UiObjectNotFoundException e) {
// Do nothing because second click is normaly not necessary
}
} catch (UiObjectNotFoundException e) {
throw new AssertionError("OneDrive login failed");
}
awaitCompleted();
checkLoginResult("OneDrive", ONEDRIVE);
}
@Test
public void test05LoginWebdavCloudLeadsToLoggedInWebdavCloud() {
openCloudServices(device);
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(WEBDAV, click()));
LoginWebdavClouds.loginWebdavClouds(activityTestRule.getActivity());
}
@Test
public void test06LoginLocalCloudLeadsToLoggedInLocalCloud() {
openCloudServices(device);
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(LOCAL, click()));
LoginLocalClouds.loginLocalClouds(device);
}
}

View File

@ -1,668 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import org.cryptomator.domain.CloudType;
import org.cryptomator.presentation.CryptomatorApp;
import org.cryptomator.presentation.R;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import static android.R.id.button1;
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.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.action.ViewActions.swipeDown;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static java.lang.String.format;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.TestUtil.DROPBOX;
import static org.cryptomator.presentation.ui.TestUtil.GOOGLE_DRIVE;
import static org.cryptomator.presentation.ui.TestUtil.LOCAL;
import static org.cryptomator.presentation.ui.TestUtil.ONEDRIVE;
import static org.cryptomator.presentation.ui.TestUtil.WEBDAV;
import static org.cryptomator.presentation.ui.TestUtil.addFolderInVaultsRoot;
import static org.cryptomator.presentation.ui.TestUtil.chooseSdCard;
import static org.cryptomator.presentation.ui.TestUtil.isToastDisplayed;
import static org.cryptomator.presentation.ui.TestUtil.removeFolderInVault;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.checkEmptyFolderHint;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.checkFileOrFolderAlreadyExistsErrorMessage;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.openSettings;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.withRecyclerView;
import static org.cryptomator.presentation.ui.activity.FolderOperationsTest.openFolder;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assume.assumeThat;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(Parameterized.class)
public class FileOperationsTest {
private final UiDevice device = UiDevice.getInstance(getInstrumentation());
private final Context context = InstrumentationRegistry.getTargetContext();
private final Integer cloudId;
@Rule
public ActivityTestRule<SplashActivity> activityTestRule //
= new ActivityTestRule<>(SplashActivity.class);
private String packageName;
public FileOperationsTest(Integer cloudId, String cloudName) {
this.cloudId = cloudId;
}
@Parameterized.Parameters(name = "{1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {{DROPBOX, "DROPBOX"}, {GOOGLE_DRIVE, "GOOGLE_DRIVE"}, {ONEDRIVE, "ONEDRIVE"}, {WEBDAV, "WEBDAV"}, {LOCAL, "LOCAL"}});
}
static void isPermissionShown(UiDevice device) {
if (!device //
.findObject(new UiSelector().text("ALLOW")) //
.waitForExists(1000L)) {
throw new AssertionError("View with text <???> not found!");
}
}
static void grantPermission(UiDevice device) {
try {
device //
.findObject(new UiSelector().text("ALLOW")) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Permission not found");
}
}
static void openFile(int nodePosition) {
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(nodePosition, R.id.cloudFileText)) //
.perform(click());
}
@Test
public void test00UploadFileWithCancelPressedWhileUploadingLeadsToNoNewFileInVault() {
assumeThat(cloudId, is(not(LOCAL)));
packageName = activityTestRule.getActivity().getPackageName();
String nodeName = "foo.pdf";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
uploadFile(nodeName);
onView(withId(android.R.id.button3)) //
.perform(click());
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(swipeDown());
awaitCompleted();
try {
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(1, R.id.cloudFileText)) //
.check(matches(withText(nodeName)));
throw new AssertionError("Canceling the upload should not lead to new cloud node");
} catch (NullPointerException e) {
// do nothing
}
pressBack();
}
@Test
public void test01UploadFileLeadsToNewFileInVault() {
packageName = activityTestRule.getActivity().getPackageName();
String nodeName = "lala.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
uploadFile(nodeName);
device.waitForWindowUpdate(packageName, 15000);
checkFileDisplayText(nodeName, 1);
pressBack();
}
@Test
public void test02UploadAlreadyExistingFileAndCancelLeadsToNoNewFileInVault() {
String nodeName = "lala.png";
String subString;
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
// subString = subtextFromFile();
uploadFile(nodeName);
device.waitForWindowUpdate(packageName, 500);
onView(withText(R.string.dialog_button_cancel)) //
.perform(click());
awaitCompleted();
// assertThat(subtextFromFile(), equalTo(subString));
pressBack();
}
@Test
public void test03UploadAlreadyExistingFileAndReplaceLeadsToUpdatedFileInVault() {
String nodeName = "lala.png";
String subString;
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
awaitCompleted();
subString = subtextFromFile();
uploadFile(nodeName);
device.waitForWindowUpdate(packageName, 500);
onView(withText(R.string.dialog_existing_file_positive_button)) //
.perform(click());
awaitCompleted();
// assertThat(subtextFromFile(), not(equalTo(subString)));
pressBack();
}
@Test
public void test04OpenFileLeadsToOpenFile() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFile(1);
device.waitForWindowUpdate(null, 25000);
device.pressBack();
awaitCompleted();
pressBack();
}
@Test
public void test05RenameFileLeadsToFileWithNewName() {
String fileName = "foo.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
renameFileTo(fileName, 1);
checkFileDisplayText(fileName, 1);
pressBack();
}
@Test
public void test06RenameFileToExistingFolderLeadsToNothingChanged() {
String fileName = "testFolder";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
renameFileTo(fileName, 1);
checkFileOrFolderAlreadyExistsErrorMessage(fileName);
onView(withId(android.R.id.button2)) //
.perform(click());
checkFileDisplayText("foo.png", 1);
pressBack();
}
@Test
public void test07MoveFileLeadsToFileWithNewLocation() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openSettings(device, 1);
openMoveFile();
openFolder(0);
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
openFolder(0);
checkFileDisplayText("foo.png", 0);
pressBack();
pressBack();
}
@Test
public void test08MoveWithExistingFileLeadsToNoNewFile() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
openSettings(device, 0);
openMoveFile();
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
isToastDisplayed( //
format( //
InstrumentationRegistry //
.getTargetContext() //
.getString(R.string.error_file_or_folder_exists), //
"foo.png"), //
activityTestRule);
pressBack();
pressBack();
pressBack();
pressBack();
}
@Test
public void test09MoveWithExistingFolderLeadsToNoNewFile() {
ApplicationComponent appComponent = ((CryptomatorApp) activityTestRule.getActivity().getApplication()).getComponent();
String moveFileNameAndTmpFolder = "foo.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
addFolderInVaultsRoot(appComponent, moveFileNameAndTmpFolder, CloudType.values()[cloudId]);
awaitCompleted();
refreshCloudNodes();
openFolder(1);
openSettings(device, 0);
openMoveFile();
pressBack();
awaitCompleted();
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
isToastDisplayed( //
InstrumentationRegistry //
.getTargetContext() //
.getString(R.string.error_file_or_folder_exists), //
activityTestRule);
removeFolderInVault(appComponent, moveFileNameAndTmpFolder, CloudType.values()[cloudId]);
pressBack();
pressBack();
pressBack();
}
@Test
public void test10ShareFileWithCryptomatorLeadsToNewFileInVault() {
String newFileName = "fooBar.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
shareFile(newFileName, cloudId, 0);
isToastDisplayed(context.getString(R.string.screen_share_files_msg_success), activityTestRule);
refreshCloudNodes();
checkFileDisplayText(newFileName, 1);
pressBack();
pressBack();
}
@Test
public void test11ShareExistingFileAndReplaceWithCryptomatorLeadsToUpdatedFileInVault() {
String newFileName = "fooBar.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
shareFile(newFileName, cloudId, 0);
onView(withId(android.R.id.button1)) //
.perform(click());
awaitCompleted();
isToastDisplayed(context.getString(R.string.screen_share_files_msg_success), activityTestRule);
refreshCloudNodes();
checkFileDisplayText(newFileName, 1); // check before and compare with after upload
pressBack();
pressBack();
}
@Test
public void test12ShareExistingFileWithoutReplaceWithCryptomatorLeadsToNotUpdatedFileInVault() {
String newFileName = "fooBar.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
shareFile(newFileName, cloudId, 0);
onView(withId(android.R.id.button3)) //
.perform(click());
pressBack();
pressBack();
pressBack();
}
@Test
public void test13RenameFileToExistingFileLeadsToNothingChanged() {
String fileName = "fooBar.png";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
renameFileTo(fileName, 0);
checkFileOrFolderAlreadyExistsErrorMessage(fileName);
onView(withId(android.R.id.button2)) //
.perform(click());
awaitCompleted();
checkFileDisplayText("foo.png", 0);
pressBack();
pressBack();
}
@Test
public void test14DeleteFileLeadsToRemovedFile() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
awaitCompleted();
openFolder(0);
deleteNodeOnPosition(0);
awaitCompleted();
deleteNodeOnPosition(0);
checkEmptyFolderHint();
pressBack();
deleteTestFolder();
pressBack();
}
private void deleteNodeOnPosition(int position) {
openSettings(device, position);
onView(withId(R.id.delete_file)) //
.perform(click());
awaitCompleted();
onView(withId(android.R.id.button1)) //
.perform(click());
}
private void refreshCloudNodes() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(swipeDown());
awaitCompleted();
}
private void shareFile(String newFilename, int vaultPosition, int filePosition) {
awaitCompleted();
openSettings(device, filePosition);
openEncryptWithCryptomator();
chooseShareLocation(vaultPosition);
checkPathInSharingScreen("/testFolder", vaultPosition);
onView(withId(R.id.fileName)) //
.perform(replaceText(newFilename), closeSoftKeyboard());
onView(withId(R.id.saveFiles)) //
.perform(click());
awaitCompleted();
}
private void chooseShareLocation(int nodePosition) {
onView(withRecyclerView(R.id.locationsRecyclerView) //
.atPositionOnView(nodePosition, R.id.vaultName)) //
.perform(click());
device.waitForWindowUpdate(packageName, 300);
onView(withRecyclerView(R.id.locationsRecyclerView) //
.atPositionOnView(nodePosition, R.id.chooseFolderLocation)) //
.perform(click());
openFolder(0);
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
awaitCompleted();
}
private void checkPathInSharingScreen(String path, int nodePosition) {
onView(withRecyclerView(R.id.locationsRecyclerView) //
.atPositionOnView(nodePosition, R.id.chosenLocation)) //
.check(matches(withText(path)));
}
private void deleteTestFolder() {
awaitCompleted();
openSettings(device, 0);
onView(withId(R.id.delete_folder)) //
.perform(click());
awaitCompleted();
onView(withId(android.R.id.button1)) //
.perform(click());
awaitCompleted();
checkEmptyFolderHint();
}
private void uploadFile(String nodeName) {
awaitCompleted();
onView(withId(R.id.floatingActionButton)) //
.perform(click());
onView(withId(R.id.upload_files)) //
.perform(click());
chooseSdCard(device);
try {
device //
.findObject(new UiSelector().text(nodeName)) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Image " + nodeName + " not available");
}
}
private void renameFileTo(String name, int nodePosition) {
awaitCompleted();
openSettings(device, nodePosition);
onView(withId(R.id.rename_file)) //
.perform(click());
onView(withId(R.id.et_rename)) //
.perform(replaceText(name), closeSoftKeyboard());
onView(allOf( //
withId(button1), //
withText(R.string.dialog_rename_node_positive_button))) //
.perform(click());
awaitCompleted();
}
private void checkFileDisplayText(String assertNodeText, int nodePosition) {
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(nodePosition, R.id.cloudFileText)) //
.check(matches(withText(assertNodeText)));
}
private void openMoveFile() {
awaitCompleted();
onView(withId(R.id.move_file)) //
.perform(click());
awaitCompleted();
}
private void openEncryptWithCryptomator() {
openShareFile();
try {
device //
.findObject(new UiSelector().text(context.getString(R.string.share_with_label))) //
.waitForExists(30000L);
device //
.findObject(new UiSelector().text(context.getString(R.string.share_with_label))) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Share with Cryptomator not available");
}
awaitCompleted();
}
private void openShareFile() {
awaitCompleted();
onView(withId(R.id.share_file)) //
.perform(click());
awaitCompleted();
}
private String subtextFromFile() {
try {
final UiSelector docList = new UiSelector() //
.resourceId("org.cryptomator:id/cloudFileContent");
return device //
.findObject(docList.childSelector(new UiSelector(). //
resourceId("org.cryptomator:id/cloudFileSubText") //
.index(0))) //
.getText();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Folder 0 not found");
}
}
}

View File

@ -1,313 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.uiautomator.UiDevice;
import org.cryptomator.presentation.R;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import java.util.Arrays;
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.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.TestUtil.DROPBOX;
import static org.cryptomator.presentation.ui.TestUtil.GOOGLE_DRIVE;
import static org.cryptomator.presentation.ui.TestUtil.LOCAL;
import static org.cryptomator.presentation.ui.TestUtil.ONEDRIVE;
import static org.cryptomator.presentation.ui.TestUtil.WEBDAV;
import static org.cryptomator.presentation.ui.TestUtil.isToastDisplayed;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.checkEmptyFolderHint;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.checkFileOrFolderAlreadyExistsErrorMessage;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.openSettings;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.withRecyclerView;
import static org.hamcrest.Matchers.allOf;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(Parameterized.class)
public class FolderOperationsTest {
private final UiDevice device = UiDevice.getInstance(getInstrumentation());
private final Context context = InstrumentationRegistry.getTargetContext();
private final Integer cloudId;
@Rule
public ActivityTestRule<SplashActivity> activityTestRule //
= new ActivityTestRule<>(SplashActivity.class);
public FolderOperationsTest(Integer cloudId, String cloudName) {
this.cloudId = cloudId;
}
@Parameterized.Parameters(name = "{1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {{DROPBOX, "DROPBOX"}, {GOOGLE_DRIVE, "GOOGLE_DRIVE"}, {ONEDRIVE, "ONEDRIVE"}, {WEBDAV, "WEBDAV"}, {LOCAL, "LOCAL"}});
}
static void openFolder(int nodePosition) {
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(nodePosition, R.id.cloudFolderText)) //
.perform(click());
awaitCompleted();
}
@Test
public void test00CreateFolderLeadsToFolderInVault() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
String folderName = "testFolder";
createFolder(folderName);
checkFolderCreationResult(folderName, "/0/testVault", 0);
pressBack();
folderName = "testFolder1";
createFolder(folderName);
checkFolderCreationResult(folderName, "/0/testVault", 1);
pressBack();
pressBack();
}
@Test
public void test01CreateExistingFolderLeadsToNoNewFolderInVault() {
String folderName = "testFolder";
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
awaitCompleted();
createFolder(folderName);
checkFileOrFolderAlreadyExistsErrorMessage(folderName);
onView(withId(android.R.id.button2)) //
.perform(click());
awaitCompleted();
pressBack();
}
@Test
public void test02OpenFolderLeadsToOpenFolder() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
checkEmptyFolderHint();
pressBack();
pressBack();
}
@Test
public void test03RenameFolderLeadsToFolderWithNewName() {
String newFolderName = "testFolder2";
int nodePosition = 1;
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
renameFolderTo(newFolderName, nodePosition);
checkFolderDisplayText(newFolderName, nodePosition);
pressBack();
}
@Test
public void test04RenameFolderToAlreadyExistFolderLeadsToSameFolderName() {
String newFolderName = "testFolder";
int nodePosition = 1;
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
renameFolderTo(newFolderName, nodePosition);
checkFileOrFolderAlreadyExistsErrorMessage(newFolderName);
onView(withId(android.R.id.button2)) //
.perform(click());
awaitCompleted();
pressBack();
}
@Test
public void test05MoveFolderLeadsToFolderWithNewLocation() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openSettings(device, 1);
openMoveFolder();
openFolder(0);
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
openFolder(0);
checkFolderDisplayText("testFolder2", 0);
openFolder(0);
checkEmptyFolderHint();
pressBack();
pressBack();
pressBack();
}
@Test
public void test06MoveFolderToAlreadyExistingFolderLeadsToErrorMessage() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openSettings(device, 0);
openMoveFolder();
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
awaitCompleted();
isToastDisplayed( //
context.getString(R.string.error_file_or_folder_exists), //
activityTestRule);
pressBack();
pressBack();
}
@Test
public void test07DeleteFolderLeadsToRemovedFolder() {
awaitCompleted();
onView(withId(R.id.recyclerView)) //
.perform(actionOnItemAtPosition(cloudId, click()));
openFolder(0);
openSettings(device, 0);
onView(withId(R.id.delete_folder)) //
.perform(click());
awaitCompleted();
onView(withId(android.R.id.button1)) //
.perform(click());
awaitCompleted();
checkEmptyFolderHint();
pressBack();
pressBack();
}
private void openMoveFolder() {
onView(withId(R.id.move_folder)) //
.perform(click());
}
private void createFolder(String name) {
awaitCompleted();
onView(withId(R.id.floatingActionButton)) //
.perform(click());
onView(withId(R.id.create_new_folder)) //
.perform(click());
onView(withId(R.id.et_folder_name)) //
.perform(replaceText(name), closeSoftKeyboard());
onView(allOf( //
withId(android.R.id.button1), //
withText(R.string.screen_enter_vault_name_button_text))) //
.perform(click());
awaitCompleted();
}
private void checkFolderCreationResult(String folderName, String path, int position) {
checkFolderDisplayText(folderName, position);
openSettings(device, position);
onView(allOf( //
withId(R.id.tv_folder_path), //
withText(path))) //
.check(matches(withText(path)));
awaitCompleted();
}
private void renameFolderTo(String name, int nodePosition) {
awaitCompleted();
openSettings(device, nodePosition);
onView(withId(R.id.change_cloud)) //
.perform(click());
onView(withId(R.id.et_rename)) //
.perform(replaceText(name), closeSoftKeyboard());
onView(allOf( //
withId(android.R.id.button1), //
withText(R.string.dialog_rename_node_positive_button))) //
.perform(click());
awaitCompleted();
}
private void checkFolderDisplayText(String assertNodeText, int nodePosition) {
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(nodePosition, R.id.cloudFolderText)) //
.check(matches(withText(assertNodeText)));
}
}

View File

@ -1,80 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import org.cryptomator.presentation.R;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.TestUtil.chooseSdCard;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.withRecyclerView;
public class LoginLocalClouds {
private static UiDevice device;
public static void loginLocalClouds(UiDevice uiDevice) {
device = uiDevice;
String folderName = "0";
createNewStorageAccessCloudCloud(folderName);
awaitCompleted();
checkResult(folderName);
}
private static void createNewStorageAccessCloudCloud(String folderName) {
onView(withId(R.id.floating_action_button)) //
.perform(click());
awaitCompleted();
chooseSdCard(device);
awaitCompleted();
openFolder0();
awaitCompleted();
chooseFolder(device);
}
private static void openFolder0() {
try {
final UiSelector docList = new UiSelector() //
.resourceId("com.android.documentsui:id/container_directory") //
.childSelector( //
new UiSelector() //
.resourceId("com.android.documentsui:id/dir_list"));
device //
.findObject(docList.childSelector(new UiSelector().text("0"))) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Folder 0 not found");
}
}
public static void chooseFolder(UiDevice device) {
try {
final UiSelector docList = new UiSelector() //
.resourceId("com.android.documentsui:id/container_save");
device //
.findObject(docList.childSelector(new UiSelector().resourceId("android:id/button1"))) //
.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("Folder 0 not found");
}
}
private static void checkResult(String folderName) {
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(0, R.id.cloudText)) //
.perform(click());
}
}

View File

@ -1,168 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import org.cryptomator.presentation.R;
import java.util.Collections;
import java.util.List;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.pressBack;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.activity.LoginWebdavClouds.WebdavCloudCredentials.notSpecialWebdavClouds;
import static org.hamcrest.Matchers.allOf;
class LoginWebdavClouds {
private static final String localUrl = "192.168.0.108";
static void loginWebdavClouds(SplashActivity activity) {
loginStandardWebdavClouds();
/*
* loginAuthenticationFailWebdavCloud(activity);
*
* loginSelfSignedWebdavCloud();
*
* loginRedirectToHttpsWebdavCloud();
*
* loginRedirectToUrlWebdavCloud();
*/
}
private static void loginStandardWebdavClouds() {
for (WebdavCloudCredentials webdavCloudCredential : notSpecialWebdavClouds()) {
createNewCloud();
enterCredentials(webdavCloudCredential);
startLoginProcess();
awaitCompleted();
checkResult(webdavCloudCredential);
}
pressBack();
}
private static void createNewCloud() {
onView(withId(R.id.floating_action_button)) //
.perform(click());
}
private static void startLoginProcess() {
onView(withId(R.id.createCloudButton)) //
.perform(click());
}
/*
* private static void loginAuthenticationFailWebdavCloud(SplashActivity activity) {
* createNewCloud();
* enterCredentials(AUTHENTICATION_FAIL);
* startLoginProcess();
*
* onView(withText(R.string.error_authentication_failed)) //
* .inRoot(withDecorView(not(is(activity.getWindow().getDecorView())))) //
* .check(matches(isDisplayed()));
*
* onView(allOf( //
* withId(R.id.et_url_port), //
* withText(AUTHENTICATION_FAIL.url)));
*
* onView(allOf( //
* withId(R.id.et_user), //
* withText(AUTHENTICATION_FAIL.username)));
*
* onView(allOf( //
* withId(R.id.et_password), //
* withText(AUTHENTICATION_FAIL.password)));
*
* pressBack();
* }
*
* private static void loginSelfSignedWebdavCloud() {
* createNewCloud();
* enterCredentials(SELF_SIGNED_HTTPS);
* startLoginProcess();
* clickOk();
* startLoginProcess();
* checkResult(SELF_SIGNED_HTTPS);
* }
*
* private static void loginRedirectToHttpsWebdavCloud() {
* createNewCloud();
* enterCredentials(REDIRECT_TO_HTTPS);
* startLoginProcess();
* clickOk();
* clickOk();
* startLoginProcess();
* checkResult(REDIRECT_TO_HTTPS);
* }
*
* private static void loginRedirectToUrlWebdavCloud() {
* createNewCloud();
* enterCredentials(REDIRECT_TO_URL);
* startLoginProcess();
* clickOk();
* startLoginProcess();
* }
*/
private static void enterCredentials(WebdavCloudCredentials webdavCloudCredential) {
onView(withId(R.id.urlPortEditText)) //
.perform(replaceText(webdavCloudCredential.url));
onView(withId(R.id.userNameEditText)) //
.perform(replaceText(webdavCloudCredential.username));
onView(withId(R.id.passwordEditText)) //
.perform( //
replaceText(webdavCloudCredential.password), //
closeSoftKeyboard());
}
private static void checkResult(WebdavCloudCredentials webdavCloudCredential) {
onView(allOf( //
withId(R.id.cloudText), //
withText(webdavCloudCredential.displayUrl)));
onView(allOf( //
withId(R.id.cloudSubText), //
withText(webdavCloudCredential.username + "")));
}
enum WebdavCloudCredentials {
GMX("https://webdav.mc.gmx.net/", "webdav.mc.gmx.net", "jraufelder@gmx.de", "mG7!3B3Mx"), //
/*
* FREENET("https://webmail.freenet.de/webdav", "webmail.freenet.de", "milestone@freenet.de", "rF7!3B3Et")
*
* , //
* /*
* AUTHENTICATION_FAIL("https://webdav.mc.gmx.net/", "webdav.mc.gmx.net", "bla@bla.de", "bla"), //
* SELF_SIGNED_HTTPS("https://" + localUrl + "/webdav", localUrl + "/webdav", "bla@bla.de", "bla"), //
* REDIRECT_TO_HTTPS("http://" + localUrl + "/webdav", localUrl + "/webdav", "bla@bla.de", "bla"), //
* REDIRECT_TO_URL("https://" + localUrl + "/bar/baz", localUrl + "/bar/baz", "bla@bla.de", "bla")
*/;
private final String url;
private final String displayUrl;
private final String username;
private final String password;
WebdavCloudCredentials(String url, String displayUrl, String username, String password) {
this.url = url;
this.displayUrl = displayUrl;
this.username = username;
this.password = password;
}
static List<WebdavCloudCredentials> notSpecialWebdavClouds() {
return Collections.singletonList(GMX/* , FREENET */);
}
}
}

View File

@ -1,412 +0,0 @@
package org.cryptomator.presentation.ui.activity;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiSelector;
import org.cryptomator.domain.CloudType;
import org.cryptomator.presentation.CryptomatorApp;
import org.cryptomator.presentation.R;
import org.cryptomator.presentation.di.component.ApplicationComponent;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import java.util.Arrays;
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.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.cryptomator.domain.executor.BackgroundTasks.awaitCompleted;
import static org.cryptomator.presentation.ui.TestUtil.DROPBOX;
import static org.cryptomator.presentation.ui.TestUtil.GOOGLE_DRIVE;
import static org.cryptomator.presentation.ui.TestUtil.LOCAL;
import static org.cryptomator.presentation.ui.TestUtil.ONEDRIVE;
import static org.cryptomator.presentation.ui.TestUtil.WEBDAV;
import static org.cryptomator.presentation.ui.TestUtil.isToastDisplayed;
import static org.cryptomator.presentation.ui.TestUtil.removeFolderInCloud;
import static org.cryptomator.presentation.ui.TestUtil.waitForIdle;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.checkEmptyFolderHint;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.checkFileOrFolderAlreadyExistsErrorMessage;
import static org.cryptomator.presentation.ui.activity.BasicNodeOperationsUtil.withRecyclerView;
import static org.cryptomator.presentation.ui.activity.FileOperationsTest.grantPermission;
import static org.cryptomator.presentation.ui.activity.FileOperationsTest.isPermissionShown;
import static org.cryptomator.presentation.ui.activity.FileOperationsTest.openFile;
import static org.cryptomator.presentation.ui.activity.FolderOperationsTest.openFolder;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(Parameterized.class)
public class VaultsOperationsTest {
@Rule
public final ActivityTestRule<SplashActivity> activityTestRule = new ActivityTestRule<>(SplashActivity.class);
private final UiDevice device = UiDevice.getInstance(getInstrumentation());
private final Context context = InstrumentationRegistry.getTargetContext();
private final Integer cloudId;
public VaultsOperationsTest(Integer cloudId, String cloudName) {
this.cloudId = cloudId;
}
@Parameterized.Parameters(name = "{1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {{DROPBOX, "DROPBOX"}, {GOOGLE_DRIVE, "GOOGLE_DRIVE"}, {ONEDRIVE, "ONEDRIVE"}, {WEBDAV, "WEBDAV"}, {LOCAL, "LOCAL"}});
}
@Test
public void test00CreateNewVaultsLeadsToNewVaults() {
ApplicationComponent appComponent = ((CryptomatorApp) activityTestRule.getActivity().getApplication()).getComponent();
String path = "0/tempVault/";
awaitCompleted();
// Permission problem
if (cloudId != LOCAL) {
removeFolderInCloud(appComponent, path, CloudType.values()[cloudId]);
removeFolderInCloud(appComponent, "0/testVault/", CloudType.values()[cloudId]);
removeFolderInCloud(appComponent, "0/testLoggedInVault/", CloudType.values()[cloudId]);
}
onView(withId(R.id.floating_action_button)) //
.perform(click());
awaitCompleted();
onView(withId(R.id.create_new_vault)) //
.perform(click());
createVault(cloudId, appComponent, path);
awaitCompleted();
unlockVault("tempVault", cloudId);
awaitCompleted();
checkEmptyFolderHint();
pressBack();
}
@Test
public void test01RenameLoggedInVaultToAlreadyExistingNameLeadsToNothingChanged() {
String vaultName = "tempVault";
renameVault(cloudId, vaultName);
checkFileOrFolderAlreadyExistsErrorMessage(vaultName);
onView(withId(android.R.id.button2)) //
.perform(click());
checkVault(cloudId, vaultName);
}
@Test
public void test02ChangeLoggedInVaultPasswordLeadsToNewPassword() {
String oldPassword = "tempVault";
String newPassword = "foo";
changePassword(cloudId, oldPassword, newPassword);
isToastDisplayed(context.getString(R.string.screen_vault_list_change_password_successful), activityTestRule);
}
@Test
public void test03RenameLoggedInVaultToNewNameLeadsToNewName() {
String vaultName = "testLoggedInVault";
renameVault(cloudId, vaultName);
checkVault(cloudId, vaultName);
}
@Test
public void test04RenameLoggedOutVaultToAlreadyExistingNameLeadsToNothingChanged() {
String vaultName = "testLoggedInVault";
renameVault(cloudId, vaultName);
checkFileOrFolderAlreadyExistsErrorMessage(vaultName);
onView(withId(android.R.id.button2)) //
.perform(click());
}
@Test
public void test05RenameLoggedOutVaultToNewNameLeadsToNewName() {
String vaultName = "testVault";
renameVault(cloudId, vaultName);
checkVault(cloudId, vaultName);
}
@Test
public void test06ChangeLoggedOutVaultPasswordLeadsToNewPassword() {
String oldPassword = "foo";
String newPassword = "testVault";
changePassword(cloudId, oldPassword, newPassword);
isToastDisplayed(context.getString(R.string.screen_vault_list_change_password_successful), activityTestRule);
}
@Test
public void test07DeleteVaultsLeadsToDeletedVaults() {
waitForIdle(device);
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(cloudId, R.id.settings)) //
.perform(click());
waitForIdle(device);
onView(withId(R.id.delete_vault)) //
.perform(click());
awaitCompleted();
onView(withId(android.R.id.button1)) //
.perform(click());
onView(withId(R.id.tv_creation_hint));
}
@Test
public void test08addExistingVaultsLeadsToAddedVaults() {
waitForIdle(device);
onView(withId(R.id.floating_action_button)) //
.perform(click());
waitForIdle(device);
onView(withId(R.id.add_existing_vault)) //
.perform(click());
openVault(cloudId);
awaitCompleted();
unlockVault("testVault", cloudId);
awaitCompleted();
checkEmptyFolderHint();
pressBack();
}
private void renameVault(int position, String vaultName) {
awaitCompleted();
waitForIdle(device);
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(position, R.id.settings)) //
.perform(click());
waitForIdle(device);
onView(withId(R.id.et_rename)) //
.perform(click());
awaitCompleted();
waitForIdle(device);
onView(withId(R.id.et_rename)) //
.perform(replaceText("tempVault"), closeSoftKeyboard());
onView(withId(R.id.et_rename)) //
.perform(replaceText(vaultName), closeSoftKeyboard());
onView(withId(android.R.id.button1)) //
.perform(click());
awaitCompleted();
}
private void createVault(int vaultPosition, ApplicationComponent appComponent, String path) {
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(vaultPosition, R.id.cloud)) //
.perform(click());
String vaultnameAndPassword = "tempVault";
awaitCompleted();
switch (vaultPosition) {
case WEBDAV:
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(0, R.id.cloudText)) //
.perform(click());
break;
case LOCAL:
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(0, R.id.cloudText)) //
.perform(click());
awaitCompleted();
isPermissionShown(device);
grantPermission(device);
removeFolderInCloud(appComponent, path, CloudType.LOCAL);
removeFolderInCloud(appComponent, "0/testVault/", CloudType.LOCAL);
removeFolderInCloud(appComponent, "0/testLoggedInVault/", CloudType.LOCAL);
break;
}
awaitCompleted();
onView(withId(R.id.vaultNameEditText)) //
.perform(replaceText(vaultnameAndPassword), closeSoftKeyboard());
awaitCompleted();
onView(withId(R.id.createVaultButton)) //
.perform(click());
awaitCompleted();
openFolder(0);
onView(withId(R.id.chooseLocationButton)) //
.perform(click());
awaitCompleted();
onView(withId(R.id.passwordEditText)) //
.perform(replaceText(vaultnameAndPassword));
onView(withId(R.id.passwordRetypedEditText)) //
.perform(replaceText(vaultnameAndPassword), closeSoftKeyboard());
awaitCompleted();
onView(withId(R.id.createVaultButton)) //
.perform(click());
}
private void openVault(int vaultPosition) {
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(vaultPosition, R.id.cloud)) //
.perform(click());
awaitCompleted();
switch (vaultPosition) {
case WEBDAV:
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(0, R.id.cloudText)) //
.perform(click());
break;
case LOCAL:
awaitCompleted();
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(0, R.id.cloudText)) //
.perform(click());
break;
}
awaitCompleted();
openFolder(0);
awaitCompleted();
openFolder(0);
awaitCompleted();
openFile(1);
}
private void unlockVault(String vaultPassword, int vaultPosition) {
waitForIdle(device);
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(vaultPosition, R.id.vaultName)) //
.perform(click());
device //
.findObject(new UiSelector().text("Password")) //
.waitForExists(30000L);
onView(withId(R.id.et_password)) //
.perform(replaceText(vaultPassword), closeSoftKeyboard());
onView(withId(android.R.id.button1)) //
.perform(click());
awaitCompleted();
}
private void changePassword(int position, String oldPassword, String newPassword) {
awaitCompleted();
waitForIdle(device);
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(position, R.id.settings)) //
.perform(click());
waitForIdle(device);
onView(withId(R.id.change_password)) //
.perform(click());
awaitCompleted();
onView(withId(R.id.et_old_password)) //
.perform(replaceText(oldPassword));
onView(withId(R.id.et_new_password)) //
.perform(replaceText(newPassword));
onView(withId(R.id.et_new_retype_password)) //
.perform(replaceText(newPassword), closeSoftKeyboard());
onView(withId(android.R.id.button1)) //
.perform(click());
awaitCompleted();
}
private void checkVault(int position, String name) {
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(position, R.id.vaultName)) //
.check(matches(withText(name)));
onView(withRecyclerView(R.id.recyclerView) //
.atPositionOnView(position, R.id.vaultPath)) //
.check(matches(withText("/0/" + name)));
}
}

View File

@ -1,21 +0,0 @@
package org.cryptomator.presentation.ui.activity.suite;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
class FailureListener extends RunListener {
private final RunNotifier runNotifier;
FailureListener(RunNotifier runNotifier) {
super();
this.runNotifier = runNotifier;
}
@Override
public void testFailure(Failure failure) throws Exception {
super.testFailure(failure);
this.runNotifier.pleaseStop();
}
}

View File

@ -1,22 +0,0 @@
package org.cryptomator.presentation.ui.activity.suite;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
public class StopOnFailureSuite extends Suite {
public StopOnFailureSuite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError {
super(klass, suiteClasses);
}
public StopOnFailureSuite(Class<?> klass) throws InitializationError {
super(klass, klass.getAnnotation(Suite.SuiteClasses.class).value());
}
@Override
public void run(RunNotifier runNotifier) {
runNotifier.addListener(new FailureListener(runNotifier));
super.run(runNotifier);
}
}

View File

@ -1,21 +0,0 @@
package org.cryptomator.presentation.ui.activity.suite;
import org.cryptomator.presentation.ui.activity.CloudsOperationsTest;
import org.cryptomator.presentation.ui.activity.FileOperationsTest;
import org.cryptomator.presentation.ui.activity.FolderOperationsTest;
import org.cryptomator.presentation.ui.activity.VaultsOperationsTest;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@Ignore
@RunWith(StopOnFailureSuite.class)
@Suite.SuiteClasses({ //
CloudsOperationsTest.class, //
VaultsOperationsTest.class, //
FolderOperationsTest.class, //
FileOperationsTest.class //
})
public class UiTestSuite {
}