Remove unmaintained UI tests and remove deprecated AndroidJunit4 usage
This commit is contained in:
parent
0ff8ac3cb5
commit
c68e30e142
@ -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}",
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 {
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user