diff --git a/briar-android/build.gradle b/briar-android/build.gradle index 1976c0edd..c31ac18f2 100644 --- a/briar-android/build.gradle +++ b/briar-android/build.gradle @@ -90,15 +90,10 @@ dependencies { implementation project(path: ':bramble-core', configuration: 'default') implementation project(':bramble-android') -// implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.appcompat:appcompat:1.1.0' -// implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.preference:preference:1.1.0' - implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.annotation:annotation:1.1.0' implementation 'androidx.exifinterface:exifinterface:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.android.material:material:1.0.0' implementation 'ch.acra:acra:4.11' @@ -121,17 +116,21 @@ dependencies { compileOnly 'javax.annotation:jsr250-api:1.0' + def espressoVersion = '3.2.0' + def jmockVersion = '2.8.2' testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-core', configuration: 'testOutput') - testImplementation 'org.robolectric:robolectric:4.3' - testImplementation 'org.robolectric:shadows-support-v4:3.3.2' + testImplementation 'androidx.test:runner:1.2.0' + testImplementation 'androidx.test.ext:junit:1.1.1' + testImplementation 'androidx.fragment:fragment-testing:1.1.0' + testImplementation "androidx.test.espresso:espresso-core:$espressoVersion" + testImplementation 'org.robolectric:robolectric:4.3.1' testImplementation 'org.mockito:mockito-core:3.1.0' testImplementation 'junit:junit:4.12' - testImplementation "org.jmock:jmock:2.8.2" - testImplementation "org.jmock:jmock-junit4:2.8.2" - testImplementation "org.jmock:jmock-legacy:2.8.2" + testImplementation "org.jmock:jmock:$jmockVersion" + testImplementation "org.jmock:jmock-junit4:$jmockVersion" + testImplementation "org.jmock:jmock-legacy:$jmockVersion" - def espressoVersion = '3.2.0' androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion" androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion" androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" diff --git a/briar-android/src/test/java/org/briarproject/briar/android/account/SetPasswordFragmentTest.java b/briar-android/src/test/java/org/briarproject/briar/android/account/SetPasswordFragmentTest.java deleted file mode 100644 index d397ec167..000000000 --- a/briar-android/src/test/java/org/briarproject/briar/android/account/SetPasswordFragmentTest.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.briarproject.briar.android.account; - -import com.google.android.material.textfield.TextInputLayout; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; - -import org.briarproject.briar.R; -import org.briarproject.briar.android.TestBriarApplication; -import org.briarproject.briar.android.login.StrengthMeter; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import static junit.framework.Assert.assertEquals; -import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE; -import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG; -import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK; -import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG; -import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK; -import static org.junit.Assert.assertNotEquals; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment; - -@RunWith(RobolectricTestRunner.class) -@Config(sdk = 21, application = TestBriarApplication.class) -public class SetPasswordFragmentTest { - - private SetPasswordFragment passwordFragment = new SetPasswordFragment(); - private EditText passwordEntry; - private EditText passwordConfirmation; - private TextInputLayout passwordConfirmationWrapper; - private StrengthMeter strengthMeter; - private Button createAccountButton; - - @Mock - private SetupController setupController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - startFragment(passwordFragment, SetupActivity.class); - - View v = passwordFragment.getView(); - passwordEntry = v.findViewById(R.id.password_entry); - passwordConfirmation = v.findViewById(R.id.password_confirm); - passwordConfirmationWrapper = - v.findViewById(R.id.password_confirm_wrapper); - strengthMeter = v.findViewById(R.id.strength_meter); - createAccountButton = v.findViewById(R.id.next); - } - - @Test - public void testCreateAccountUI() { - String safePass = "really.safe.password"; - - passwordFragment.setupController = setupController; - when(setupController.needToShowDozeFragment()).thenReturn(false); - when(setupController.estimatePasswordStrength(safePass)) - .thenReturn(STRONG); - - passwordEntry.setText(safePass); - passwordConfirmation.setText(safePass); - // Confirm that the create account button is clickable - assertEquals(createAccountButton.isEnabled(), true); - createAccountButton.performClick(); - - // assert controller has been called properly - verify(setupController, times(1)).setPassword(safePass); - verify(setupController, times(1)).createAccount(); - } - - @Test - public void testStrengthMeterUI() { - // Test the meters' progress and color for several values - testStrengthMeter("1234567890ab", STRONG, StrengthMeter.GREEN); - testStrengthMeter("123456789", QUITE_STRONG, StrengthMeter.LIME); - testStrengthMeter("123456", QUITE_WEAK, StrengthMeter.YELLOW); - testStrengthMeter("123", WEAK, StrengthMeter.ORANGE); - testStrengthMeter("", NONE, StrengthMeter.RED); - } - - private void testStrengthMeter(String pass, float strength, int color) { - passwordEntry.setText(pass); - assertEquals(strengthMeter.getProgress(), - (int) (strengthMeter.getMax() * strength)); - assertEquals(color, strengthMeter.getColor()); - } - - - @Test - public void testPasswordMatchUI() { - // Password mismatch - passwordEntry.setText("really.safe.password"); - passwordConfirmation.setText("really.safe.pass"); - assertEquals(createAccountButton.isEnabled(), false); - assertEquals(passwordConfirmationWrapper.getError(), - passwordFragment.getString(R.string.passwords_do_not_match)); - // Button enabled - passwordEntry.setText("really.safe.pass"); - passwordConfirmation.setText("really.safe.pass"); - // Confirm that the password mismatch error message is not visible - assertNotEquals(passwordConfirmationWrapper.getError(), - passwordFragment.getString(R.string.passwords_do_not_match)); - // Passwords match, so button should be enabled - assertEquals(createAccountButton.isEnabled(), true); - } - -} diff --git a/briar-android/src/test/java/org/briarproject/briar/android/account/SetupActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/account/SetupActivityTest.java index 9a43d3ed6..9edfd6f3d 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/account/SetupActivityTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/account/SetupActivityTest.java @@ -1,47 +1,147 @@ package org.briarproject.briar.android.account; -import com.google.android.material.textfield.TextInputLayout; -import android.widget.EditText; +import android.view.View; import org.briarproject.briar.R; import org.briarproject.briar.android.TestBriarApplication; -import org.junit.Assert; -import org.junit.Before; +import org.briarproject.briar.android.login.StrengthMeter; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; -import org.robolectric.Robolectric; -import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static junit.framework.Assert.assertEquals; +import androidx.test.espresso.matcher.BoundedMatcher; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.clearText; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE; +import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG; +import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK; +import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG; +import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.util.StringUtils.getRandomString; +import static org.briarproject.briar.android.login.StrengthMeter.GREEN; +import static org.briarproject.briar.android.login.StrengthMeter.LIME; +import static org.briarproject.briar.android.login.StrengthMeter.ORANGE; +import static org.briarproject.briar.android.login.StrengthMeter.RED; +import static org.briarproject.briar.android.login.StrengthMeter.YELLOW; +import static org.hamcrest.Matchers.not; -@RunWith(RobolectricTestRunner.class) +@RunWith(AndroidJUnit4.class) @Config(sdk = 21, application = TestBriarApplication.class) public class SetupActivityTest { - private SetupActivity setupActivity; - private TextInputLayout nicknameEntryWrapper; - private EditText nicknameEntry; + @Rule + public ActivityScenarioRule rule = + new ActivityScenarioRule<>(SetupActivity.class); - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - setupActivity = Robolectric.setupActivity(SetupActivity.class); - nicknameEntryWrapper = - setupActivity.findViewById(R.id.nickname_entry_wrapper); - nicknameEntry = setupActivity.findViewById(R.id.nickname_entry); + @Test + public void testNicknameTooLongErrorShown() { + String longNick = getRandomString(MAX_AUTHOR_NAME_LENGTH + 1); + onView(withId(R.id.nickname_entry)).perform(typeText(longNick)); + + // Nickname should be too long + onView(withText(R.string.name_too_long)).check(matches(isDisplayed())); } @Test - public void testNicknameUI() { - Assert.assertNotNull(setupActivity); - String longNick = getRandomString(MAX_AUTHOR_NAME_LENGTH + 1); - nicknameEntry.setText(longNick); - // Nickname should be too long - assertEquals(nicknameEntryWrapper.getError(), - setupActivity.getString(R.string.name_too_long)); + public void testPasswordMatchUI() { + moveToSetPasswordFragment(); + + // error shown when passwords don't match, button is disabled + onView(withId(R.id.password_entry)).perform(typeText("123456")); + onView(withId(R.id.password_confirm)).perform(typeText("654321")); + onView(withText(R.string.passwords_do_not_match)) + .check(matches(isDisplayed())); + onView(withId(R.id.next)).check(matches(not(isEnabled()))); + + // confirming correct password, removes error, enables button + onView(withId(R.id.password_confirm)).perform(clearText()); + onView(withId(R.id.password_confirm)).perform(replaceText("123456")); + onView(withText(R.string.passwords_do_not_match)).check(doesNotExist()); + onView(withId(R.id.next)).check(matches(isEnabled())); + + // clicking the button shows progress bar, no doze because SDK_INT==21 + onView(withId(R.id.next)).perform(click()); + onView(withId(R.id.progress)).check(matches(isDisplayed())); } + + @Test + public void testStrengthMeterUI() { + moveToSetPasswordFragment(); + + onView(withId(R.id.password_entry)).perform(typeText("1234567890ab")); + onView(withId(R.id.strength_meter)) + .check(matches(strengthAndColor(STRONG, GREEN))); + + onView(withId(R.id.password_entry)).perform(clearText()); + onView(withId(R.id.password_entry)).perform(typeText("123456789")); + onView(withId(R.id.strength_meter)) + .check(matches(strengthAndColor(QUITE_STRONG, LIME))); + + onView(withId(R.id.password_entry)).perform(clearText()); + onView(withId(R.id.password_entry)).perform(typeText("123456")); + onView(withId(R.id.strength_meter)) + .check(matches(strengthAndColor(QUITE_WEAK, YELLOW))); + + onView(withId(R.id.password_entry)).perform(clearText()); + onView(withId(R.id.password_entry)).perform(typeText("123")); + onView(withId(R.id.strength_meter)) + .check(matches(strengthAndColor(WEAK, ORANGE))); + + onView(withId(R.id.password_entry)).perform(clearText()); + onView(withId(R.id.strength_meter)) + .check(matches(strengthAndColor(NONE, RED))); + } + + private void moveToSetPasswordFragment() { + onView(withId(R.id.nickname_entry)).perform(typeText("test")); + onView(withId(R.id.next)).perform(click()); + onView(withId(R.id.password_entry)).check(matches(isDisplayed())); + } + + private Matcher strengthAndColor(float strength, int color) { + return new StrengthMeterMatcher(strength, color); + } + + static class StrengthMeterMatcher + extends BoundedMatcher { + + private final float strength; + private final int color; + + private StrengthMeterMatcher(float strength, int color) { + super(StrengthMeter.class); + this.strength = strength; + this.color = color; + } + + @Override + public void describeTo(Description description) { + description.appendText("is enabled"); + } + + @Override + public boolean matchesSafely(StrengthMeter view) { + boolean strengthMatches = + view.getProgress() == (int) (view.getMax() * strength); + boolean colorMatches = color == view.getColor(); + return strengthMatches && colorMatches; + } + } + } diff --git a/briar-android/witness.gradle b/briar-android/witness.gradle index 15cafdae9..7ff3d97e9 100644 --- a/briar-android/witness.gradle +++ b/briar-android/witness.gradle @@ -1,5 +1,6 @@ dependencyVerification { verify = [ + 'androidx.activity:activity-ktx:1.0.0:activity-ktx-1.0.0.aar:be4d4c7e51a42fedb0bc6e68e9c3eba3603d3bbc2ef468689694369f98eab6c7', 'androidx.activity:activity:1.0.0:activity-1.0.0.aar:d1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d', 'androidx.annotation:annotation:1.1.0:annotation-1.1.0.jar:d38d63edb30f1467818d50aaf05f8a692dea8b31392a049bfa991b159ad5b692', 'androidx.appcompat:appcompat-resources:1.1.0:appcompat-resources-1.1.0.aar:19944d32b46551a17c347e21894b95837fbd7baaafc9e2082794344f222f7361', @@ -18,6 +19,8 @@ dependencyVerification { 'androidx.documentfile:documentfile:1.0.0:documentfile-1.0.0.aar:865a061ef2fad16522f8433536b8d47208c46ff7c7745197dfa1eeb481869487', 'androidx.drawerlayout:drawerlayout:1.0.0:drawerlayout-1.0.0.aar:9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1', 'androidx.exifinterface:exifinterface:1.0.0:exifinterface-1.0.0.aar:ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11', + 'androidx.fragment:fragment-ktx:1.1.0:fragment-ktx-1.1.0.aar:d40e525a57f21814fe8754e69c7306224ca30ed33f33c17c329b91bd839de94e', + 'androidx.fragment:fragment-testing:1.1.0:fragment-testing-1.1.0.aar:c4ae4a296df1a05708f7fde215784c7171084d0801fdc3ad12a2163a8ced2a4c', 'androidx.fragment:fragment:1.1.0:fragment-1.1.0.aar:a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496', 'androidx.interpolator:interpolator:1.0.0:interpolator-1.0.0.aar:33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a', 'androidx.legacy:legacy-support-core-ui:1.0.0:legacy-support-core-ui-1.0.0.aar:0d1260c6e7e6a337f875df71b516931e703f716e90889817cd3a20fa5ac3d947', @@ -29,6 +32,7 @@ dependencyVerification { 'androidx.lifecycle:lifecycle-process:2.1.0:lifecycle-process-2.1.0.aar:8cddd0c7f4927bbf71fb71fca000786df82cc597c99463d6916ccbe4a205a9ac', 'androidx.lifecycle:lifecycle-runtime:2.1.0:lifecycle-runtime-2.1.0.aar:e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b', 'androidx.lifecycle:lifecycle-service:2.1.0:lifecycle-service-2.1.0.aar:23516745f34f16ff7850bb1eadd55cf193dd789cba428de4bca120433e3bfd69', + 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0:lifecycle-viewmodel-ktx-2.1.0.aar:16a66d966f6a5c201e724dad836d85fcfa528a891ae5ae0e5f7556ab5bc7575f', 'androidx.lifecycle:lifecycle-viewmodel:2.1.0:lifecycle-viewmodel-2.1.0.aar:ba55fb7ac1b2828d5327cda8acf7085d990b2b4c43ef336caa67686249b8523d', 'androidx.loader:loader:1.0.0:loader-1.0.0.aar:11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025', 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0:localbroadcastmanager-1.0.0.aar:e71c328ceef5c4a7d76f2d86df1b65d65fe2acf868b1a4efd84a3f34336186d8', @@ -42,6 +46,7 @@ dependencyVerification { 'androidx.test.espresso:espresso-core:3.2.0:espresso-core-3.2.0.aar:beb4712c2520c1da30ac1f25506871f16ea5b83ee686ece5a258769df1a01e15', 'androidx.test.espresso:espresso-idling-resource:3.2.0:espresso-idling-resource-3.2.0.aar:c1a0454fe95788122ba652c3ecff7ec538c7e27de206aed970f2809fb8090d09', 'androidx.test.espresso:espresso-intents:3.2.0:espresso-intents-3.2.0.aar:b13347a543d1fe957bc901281caed8b8f8a475f702779c851fafdfed7b9467c1', + 'androidx.test.ext:junit:1.1.1:junit-1.1.1.aar:449df418d2916a0f86fe7dafb1edb09480fafb6e995d5c751c7d0d1970d4ae72', 'androidx.test.uiautomator:uiautomator:2.2.0:uiautomator-2.2.0.aar:2838e9d961dbffefbbd229a2bd4f6f82ac4fb2462975862a9e75e9ed325a3197', 'androidx.test:core:1.2.0:core-1.2.0.aar:c88b739b1c499afb792374be19b9cf829e89567f26441a74f664c0cf8de158a4', 'androidx.test:monitor:1.2.0:monitor-1.2.0.aar:fc97ca3f00f8ca30b7d5167fbd8736756048e2cc4f8e92dc891106751a5baeef', @@ -181,10 +186,15 @@ dependencyVerification { 'org.hamcrest:hamcrest-integration:1.3:hamcrest-integration-1.3.jar:70f418efbb506c5155da5f9a5a33262ea08a9e4d7fea186aa9015c41a7224ac2', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c', 'org.jetbrains.kotlin:kotlin-reflect:1.3.50:kotlin-reflect-1.3.50.jar:64583199ea5a54aefd1bd1595288925f784226ee562d1dd279011c6075b3d7a4', + 'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.31:kotlin-stdlib-common-1.3.31.jar:d6e9c54c1e6c4df21be9395de558665544c6bdc8f8076ea7518f089f82cd34fc', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50:kotlin-stdlib-common-1.3.50.jar:8ce678e88e4ba018b66dacecf952471e4d7dfee156a8a819760a5a5ff29d323c', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50:kotlin-stdlib-jdk7-1.3.50.jar:9a026639e76212f8d57b86d55b075394c2e009f1979110751d34c05c5f75d57b', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50:kotlin-stdlib-jdk8-1.3.50.jar:1b351fb6e09c14b55525c74c1f4cf48942eae43c348b7bc764a5e6e423d4da0c', + 'org.jetbrains.kotlin:kotlin-stdlib:1.3.31:kotlin-stdlib-1.3.31.jar:f38c84326543e66ed4895b20fb3ea0fca527fd5a040e1f49d0946ecf3d2b3b23', 'org.jetbrains.kotlin:kotlin-stdlib:1.3.50:kotlin-stdlib-1.3.50.jar:e6f05746ee0366d0b52825a090fac474dcf44082c9083bbb205bd16976488d6c', + 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1:kotlinx-coroutines-android-1.1.1.jar:ed6fc7d667d5c11d187894789d7bf6cf8fedccb0be75fde795b8686582a1fe32', + 'org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.1.1:kotlinx-coroutines-core-common-1.1.1.jar:033732168fd3a68a7d788294321106ae13536eae8459382a85cc1f17f88572e7', + 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1:kotlinx-coroutines-core-1.1.1.jar:ac423f8a0aa4b4e74529696ff82c0171f81a8c8ab182a1965dff25e69c1f7844', 'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c', @@ -204,18 +214,17 @@ dependencyVerification { 'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145', 'org.ow2.asm:asm:6.0:asm-6.0.jar:dd8971c74a4e697899a8e95caae4ea8760ea6c486dc6b97b1795e75760420461', 'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf', - 'org.robolectric:annotations:4.3:annotations-4.3.jar:8c10ec1a43ea8346b094a08eaf0aefbaaf749e1a80f10de6a70e7f8788735d03', - 'org.robolectric:junit:4.3:junit-4.3.jar:aaef4e59bd99e227e1a0563461363201d0b292e0703a46ea0153c576ebc686a2', - 'org.robolectric:pluginapi:4.3:pluginapi-4.3.jar:33cbde3e210cc4b7916195ef1e074b32bddc0a9d72d50dce4f935cc0919f4a63', - 'org.robolectric:plugins-maven-dependency-resolver:4.3:plugins-maven-dependency-resolver-4.3.jar:020bcfc6edbd242272dee688b68f2128b9bbcaabf1a03ae7637b913c83c64b9c', - 'org.robolectric:resources:4.3:resources-4.3.jar:739bb0d381dfc8f45abab17ac375e7e8e1156ddaa46963cbad827511794d3617', - 'org.robolectric:robolectric:4.3:robolectric-4.3.jar:c8137bad762615a28eb321465b04d6e5b0df00687125f22178479452d80e0b82', - 'org.robolectric:sandbox:4.3:sandbox-4.3.jar:c1fed5bb01925c6498bddb53a4dd5e97e11d2e9fe0dc9c5336572b6829dc0ffa', - 'org.robolectric:shadowapi:4.3:shadowapi-4.3.jar:731c9bbad67a21d86303032a8f4128ec7041b9c256ac08943f46a816307a5765', - 'org.robolectric:shadows-framework:4.3:shadows-framework-4.3.jar:0ca9dfcad19c565fc0301f737f8ef01906a2ea89e6ef92ca5aaf2c8915fca119', - 'org.robolectric:shadows-support-v4:3.3.2:shadows-support-v4-3.3.2.jar:6f689264738266e70fe08db7c04b7b5a75155994f4e3f7f311960d90486bf005', - 'org.robolectric:utils-reflector:4.3:utils-reflector-4.3.jar:e75c5d758f6c714825b331cf3e203f9233b509a0dcafa7dd296870acd6096ea4', - 'org.robolectric:utils:4.3:utils-4.3.jar:7a5159a8990d5ab68d2728609bf520db7c963574e7c4faffa3fef45242c8ea7c', + 'org.robolectric:annotations:4.3.1:annotations-4.3.1.jar:ce679af70c22620b5752aa6c1555d0653198d6370e9a93fe71b8eaaebc5ffaf6', + 'org.robolectric:junit:4.3.1:junit-4.3.1.jar:60c85ea7fd652bc4e57567cbd3c41c5d32f2c678e212b713cefa6c63570451ce', + 'org.robolectric:pluginapi:4.3.1:pluginapi-4.3.1.jar:229256a260a1d8e8d33613a3de7ccd639661a7061251c1974975ed427428b468', + 'org.robolectric:plugins-maven-dependency-resolver:4.3.1:plugins-maven-dependency-resolver-4.3.1.jar:0d6c577fdefe254659ffba5c0564d7e00c69f03e99a4ebb6c150419834cdb703', + 'org.robolectric:resources:4.3.1:resources-4.3.1.jar:93033237006b51541f8e93d65940f9040367775937d0ce9ac3f4ef72771c51b8', + 'org.robolectric:robolectric:4.3.1:robolectric-4.3.1.jar:3ef4267112ba581ee2a7ad37859bf61571404f07df85b8ad1da054f90eb57a5a', + 'org.robolectric:sandbox:4.3.1:sandbox-4.3.1.jar:405f73400d717e083b25af92fa7866a76765dd4e97cf7fd046023d4f05375a9f', + 'org.robolectric:shadowapi:4.3.1:shadowapi-4.3.1.jar:a63d13e7f3816f28ac33eea71a15c7f3f0053ecd01b08cc1e1e119af35ca1197', + 'org.robolectric:shadows-framework:4.3.1:shadows-framework-4.3.1.jar:9c69db134cdd79be751856a148020fd9b32b086bb491846eedc0a1106fcadd5e', + 'org.robolectric:utils-reflector:4.3.1:utils-reflector-4.3.1.jar:9d7bf2557947d44d6f3ed76ec5231e8b72e33eb61c65ac9e149ad307b0eb936c', + 'org.robolectric:utils:4.3.1:utils-4.3.1.jar:6f9e406cd667019a5450e473c4e2d372bff9c9ab6ef55aafcbc9843109cb1519', 'tools.fastlane:screengrab:1.2.0:screengrab-1.2.0.aar:af4ee23bb06f94404d3ab18e2ea69db8265539fc8da29f9ee45b7e472684ba83', 'uk.co.samuelwall:material-tap-target-prompt:3.0.0:material-tap-target-prompt-3.0.0.aar:e4d3c472b2d378e39a6535b7788e6c790fc9dde2d7659974e006ed8c7260911d', ]