From 19dae639ee3446229d9a457c652f589219e0082b Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Fri, 27 Nov 2020 14:08:24 +0500 Subject: [PATCH 1/5] - All clients register translation fixes --- .../fragment/AllClientsRegisterFragment.java | 10 +++ .../hf/provider/HfChildRegisterProvider.java | 8 ++- .../hf/provider/HfOpdRegisterProvider.java | 68 +++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfOpdRegisterProvider.java diff --git a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/fragment/AllClientsRegisterFragment.java b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/fragment/AllClientsRegisterFragment.java index 365cc7200..6ee31a7ed 100644 --- a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/fragment/AllClientsRegisterFragment.java +++ b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/fragment/AllClientsRegisterFragment.java @@ -6,8 +6,10 @@ import org.smartregister.chw.core.fragment.CoreAllClientsRegisterFragment; import org.smartregister.chw.hf.R; +import org.smartregister.chw.hf.provider.HfOpdRegisterProvider; import org.smartregister.chw.hf.utils.AllClientsUtils; import org.smartregister.commonregistry.CommonPersonObjectClient; +import org.smartregister.cursoradapter.RecyclerViewPaginatedAdapter; public class AllClientsRegisterFragment extends CoreAllClientsRegisterFragment { @@ -22,5 +24,13 @@ public void setupViews(View view) { protected void goToClientDetailActivity(@NonNull CommonPersonObjectClient commonPersonObjectClient) { AllClientsUtils.goToClientProfile(this.getActivity(), commonPersonObjectClient); } + + @Override + public void initializeAdapter() { + HfOpdRegisterProvider childRegisterProvider = new HfOpdRegisterProvider(getActivity(), registerActionHandler, paginationViewHandler); + clientAdapter = new RecyclerViewPaginatedAdapter(null, childRegisterProvider, context().commonrepository(this.tablename)); + clientAdapter.setCurrentlimit(20); + clientsView.setAdapter(clientAdapter); + } } diff --git a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfChildRegisterProvider.java b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfChildRegisterProvider.java index fa7c6bbc0..3bc3cf493 100644 --- a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfChildRegisterProvider.java +++ b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfChildRegisterProvider.java @@ -51,7 +51,13 @@ public void getView(Cursor cursor, SmartRegisterClient client, RegisterViewHolde @Override public void setAddressAndGender(CommonPersonObjectClient pc, RegisterViewHolder viewHolder) { String address = Utils.getValue(pc.getColumnmaps(), ChildDBConstants.KEY.FAMILY_HOME_ADDRESS, true); - String gender = Utils.getValue(pc.getColumnmaps(), DBConstants.KEY.GENDER, true); + String gender_key = Utils.getValue(pc.getColumnmaps(), DBConstants.KEY.GENDER, true); + String gender = ""; + if (gender_key.equalsIgnoreCase("Male")) { + gender = context.getString(org.smartregister.chw.core.R.string.male); + } else if (gender_key.equalsIgnoreCase("Female")) { + gender = context.getString(org.smartregister.chw.core.R.string.female); + } fillValue(viewHolder.textViewAddressGender, gender + " \u00B7 " + address); } diff --git a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfOpdRegisterProvider.java b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfOpdRegisterProvider.java new file mode 100644 index 000000000..13f671a46 --- /dev/null +++ b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/provider/HfOpdRegisterProvider.java @@ -0,0 +1,68 @@ +package org.smartregister.chw.hf.provider; + +import android.content.Context; +import android.text.TextUtils; +import android.view.View; + +import androidx.annotation.NonNull; + +import org.smartregister.chw.core.utils.CoreConstants; +import org.smartregister.chw.hf.R; +import org.smartregister.commonregistry.CommonPersonObjectClient; +import org.smartregister.family.util.DBConstants; +import org.smartregister.family.util.Utils; +import org.smartregister.opd.holders.OpdRegisterViewHolder; +import org.smartregister.opd.provider.OpdRegisterProvider; +import org.smartregister.opd.utils.OpdDbConstants; + +public class HfOpdRegisterProvider extends OpdRegisterProvider { + private final Context context; + + public HfOpdRegisterProvider(@NonNull Context context, @NonNull View.OnClickListener onClickListener, @NonNull View.OnClickListener paginationClickListener) { + super(context, onClickListener, paginationClickListener); + this.context = context; + } + + @Override + public void populatePatientColumn(CommonPersonObjectClient commonPersonObjectClient, OpdRegisterViewHolder viewHolder) { + super.populatePatientColumn(commonPersonObjectClient, viewHolder); + String registerType = org.smartregister.util.Utils.getValue(commonPersonObjectClient.getColumnmaps(), + OpdDbConstants.KEY.REGISTER_TYPE, true); + + if (!TextUtils.isEmpty(registerType)) { + viewHolder.showRegisterType(); + String type = getTranslatedRegisterType(registerType); + fillValue(viewHolder.tvRegisterType, type); + } else { + viewHolder.hideRegisterType(); + } + } + + private String getTranslatedRegisterType(String registerType) { + if (registerType.equalsIgnoreCase(CoreConstants.REGISTER_TYPE.CHILD)) { + return context.getString(R.string.menu_child); + } else if (registerType.equalsIgnoreCase(CoreConstants.REGISTER_TYPE.ANC)) { + return context.getString(R.string.menu_anc); + } else if (registerType.equalsIgnoreCase(CoreConstants.REGISTER_TYPE.PNC)) { + return context.getString(R.string.menu_pnc); + } else if (registerType.equalsIgnoreCase(CoreConstants.REGISTER_TYPE.FAMILY_PLANNING)) { + return context.getString(R.string.menu_family_planning); + } else if (registerType.equalsIgnoreCase(CoreConstants.REGISTER_TYPE.MALARIA)) { + return context.getString(R.string.menu_malaria); + } + return registerType; + } + + @Override + public void setAddressAndGender(CommonPersonObjectClient pc, OpdRegisterViewHolder viewHolder) { + super.setAddressAndGender(pc, viewHolder); + String gender_key = Utils.getValue(pc.getColumnmaps(), DBConstants.KEY.GENDER, true); + String gender = ""; + if (gender_key.equalsIgnoreCase("Male")) { + gender = context.getString(org.smartregister.chw.core.R.string.male); + } else if (gender_key.equalsIgnoreCase("Female")) { + gender = context.getString(org.smartregister.chw.core.R.string.female); + } + fillValue(viewHolder.textViewGender, gender); + } +} From 4841fd163dc568beedcf870485aae90aea56d947 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Tue, 15 Dec 2020 13:45:06 +0500 Subject: [PATCH 2/5] Update core to v1.5.22 --- opensrp-chw-hf/build.gradle | 2 +- .../smartregister/chw/hf/activity/FamilyProfileActivity.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/opensrp-chw-hf/build.gradle b/opensrp-chw-hf/build.gradle index 292372bca..d4e108a67 100644 --- a/opensrp-chw-hf/build.gradle +++ b/opensrp-chw-hf/build.gradle @@ -148,7 +148,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation('org.smartregister:opensrp-client-chw-core:1.5.10-SNAPSHOT@aar') { + implementation('org.smartregister:opensrp-client-chw-core:1.5.22-SNAPSHOT@aar') { // implementation(project(":opensrp-chw-core")) { transitive = true exclude group: 'com.android.support', module: 'appcompat-v7' diff --git a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/activity/FamilyProfileActivity.java b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/activity/FamilyProfileActivity.java index 792958418..0357bfe15 100644 --- a/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/activity/FamilyProfileActivity.java +++ b/opensrp-chw-hf/src/main/java/org/smartregister/chw/hf/activity/FamilyProfileActivity.java @@ -159,4 +159,9 @@ private void setupMenuOptions(Menu menu) { public FamilyProfilePresenter getFamilyProfilePresenter() { return (FamilyProfilePresenter) presenter; } + + @Override + public void setEventDate(String s) { + // do nothing + } } From 76823741659b9926842dcd98f2b45ba27b185054 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Mon, 14 Dec 2020 18:07:29 +0500 Subject: [PATCH 3/5] Migrate to Github actions --- .github/workflows/ci.yml | 32 ++++++++++++++++++++ .travis.yml | 59 ------------------------------------- build.gradle | 4 ++- opensrp-chw-hf/build.gradle | 3 +- 4 files changed, 36 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..e5821bb84 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Android CI with Gradle + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + unit_tests: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Install NDK + run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;21.0.6113669" --sdk_root=${ANDROID_SDK_ROOT} + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Run unit tests with Gradle + run: ./gradlew :opensrp-chw-hf:clean :opensrp-chw-hf:jacocoTestReport --stacktrace + - name: Upload coverage to Coveralls with Gradle + run: ./gradlew coveralls --stacktrace + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a63d32b51..000000000 --- a/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: android -# sudo set to required because of an issue with how TravisCI handles builds in Docker containers https://github.com/travis-ci/travis-ci/issues/3695. -# Setting sudo to required prevents Travis from testing the project in a Docker container. -sudo: required -jdk: oraclejdk8 - -env: - global: - - ANDROID_API_LEVEL=29 - - ANDROID_BUILD_TOOLS_VERSION=29.0.3 - - ANDROID_ABI=armeabi-v7a - -android: - components: - - tools - - platform-tools - # Additional components - - extra-google-google_play_services - - extra-google-m2repository - - extra-android-m2repositor - licenses: - - 'android-sdk-preview-license-52d11cd2' - - 'android-sdk-license-.+' - - 'google-gdk-license-.+' - -before_install: - - mkdir "$ANDROID_HOME/licenses" || true - - echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license" - - echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license" - - chmod +x gradlew - - echo ${ANDROID_HOME} - - echo "y" | ${ANDROID_HOME}/tools/bin/sdkmanager "platforms;android-29" - - echo "y" | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;29.0.3" - - echo "y" | ${ANDROID_HOME}/tools/bin/sdkmanager "extras;android;m2repository" - - echo "y" | ${ANDROID_HOME}/tools/bin/sdkmanager "extras;google;m2repository" - - export LANG=en_US.UTF-8 - -before_cache: - -rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - -rm -fr $HOME/.gradle/caches/*/plugin-resolution/ - -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - - $HOME/.android/build-cache - - $HOME/.gradle/native #Cache library downloaded from the gradle dependency - -script: - - echo "Travis branch is $TRAVIS_BRANCH" - - echo "Travis branch is in pull request $TRAVIS_PULL+REQUEST" - - chmod 755 gradlew - - ls -la - #Run jacocoTestReport -> Runs all unit tests & instrumentation tests - - travis_wait ./gradlew cleanBuildCache && ./gradlew :opensrp-chw-hf:jacocoTestReport coveralls --stacktrace - -notifications: - slack: - secure: fAiZ4yA7DM6nUKh7nqsCTqZBb03VEAvi5NcRu5mNh5coNn/50XNeZl+qpv7Dw70Ef85Y/k68uc6KwTGVqPXEmVq9Hk3e7lqpBNN8rufvgCYDDGPmywBmU5BhSeykKo0Ee7llM3mRR/EipjIWw1+YvMcS3hCoygf/UlMDDhG0Jo0= diff --git a/build.gradle b/build.gradle index af602935a..afbe5e6f0 100644 --- a/build.gradle +++ b/build.gradle @@ -6,10 +6,11 @@ buildscript { google() jcenter() mavenLocal() + maven{ url "https://plugins.gradle.org/m2/" } } dependencies { classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.8.3' + classpath 'gradle.plugin.org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.10.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -47,6 +48,7 @@ allprojects { maven { url "https://dl.bintray.com/ona/rdt-capture" } maven { url 'https://dl.bintray.com/ibm-watson-health/ibm-fhir-server-releases'} maven { url "http://dl.bintray.com/ona/kujaku" } + maven{ url "https://plugins.gradle.org/m2/" } } } diff --git a/opensrp-chw-hf/build.gradle b/opensrp-chw-hf/build.gradle index d4e108a67..7ba69b06e 100644 --- a/opensrp-chw-hf/build.gradle +++ b/opensrp-chw-hf/build.gradle @@ -11,7 +11,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.8.3' classpath 'io.fabric.tools:gradle:1.31.2' } } @@ -203,7 +202,7 @@ task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'crea } def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*', '**/*$ViewBinder*.*'] - def debugTree = fileTree(dir: "$project.buildDir/intermediates/classes/debug", excludes: fileFilter) + def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug/classes/", excludes: fileFilter) def mainSrc = "$project.projectDir/src/main/java" sourceDirectories.setFrom(files([mainSrc])) From 2a7ac95ffac0b5f67e733818ce4c0238a11e112c Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Mon, 14 Dec 2020 19:18:41 +0500 Subject: [PATCH 4/5] Fix coveralls config --- opensrp-chw-hf/build.gradle | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/opensrp-chw-hf/build.gradle b/opensrp-chw-hf/build.gradle index 7ba69b06e..18e18c10f 100644 --- a/opensrp-chw-hf/build.gradle +++ b/opensrp-chw-hf/build.gradle @@ -190,17 +190,13 @@ tasks.withType(Test) { task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) { reports { - html { - html.enabled = true - destination file("${buildDir}/reports/jacoco/jacocoRootReport/chw-hf-coverage") - } - - xml { - xml.enabled = true - destination file("${buildDir}/reports/jacoco/jacocoRootReport/chw-hf-coverage.xml") - } + xml.enabled = true + html.enabled = true } + getReports().getXml().setDestination(file("${buildDir}/reports/jacoco/jacocoRootReport/merged.xml")) + getReports().getHtml().setDestination(file("${buildDir}/reports/jacoco/jacocoRootReport/html")) + def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*', '**/*$ViewBinder*.*'] def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug/classes/", excludes: fileFilter) def mainSrc = "$project.projectDir/src/main/java" @@ -215,3 +211,13 @@ task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'crea tasks.withType(Test) { jacoco.includeNoLocationClasses = true } + + +tasks.coveralls { + dependsOn 'jacocoTestReport' +} + +coveralls { + jacocoReportPath = "${buildDir}/reports/jacoco/jacocoRootReport/merged.xml" + sourceDirs = ["$project.projectDir/src/main/java"] +} From c7ad9b9ba835029d87b162ef08c9f4a0fbfc73c4 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Tue, 15 Dec 2020 15:19:29 +0500 Subject: [PATCH 5/5] Added tests --- opensrp-chw-hf/build.gradle | 2 +- .../chw/hf/BaseActivityUnitTest.java | 34 +++ .../smartregister/chw/hf/BaseUnitTest.java | 14 ++ .../chw/hf/activity/LoginActivityTest.java | 228 ++++++++++++++++++ 4 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseActivityUnitTest.java create mode 100644 opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseUnitTest.java create mode 100644 opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/activity/LoginActivityTest.java diff --git a/opensrp-chw-hf/build.gradle b/opensrp-chw-hf/build.gradle index 18e18c10f..bbd6c95d7 100644 --- a/opensrp-chw-hf/build.gradle +++ b/opensrp-chw-hf/build.gradle @@ -166,7 +166,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.android.support:multidex:1.0.3' //Do not upgrade to 24.jre-1 due to compatibility issues - implementation 'com.google.guava:guava:20.0' + implementation 'com.google.guava:guava:24.1-jre' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' diff --git a/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseActivityUnitTest.java b/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseActivityUnitTest.java new file mode 100644 index 000000000..3b8d845c1 --- /dev/null +++ b/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseActivityUnitTest.java @@ -0,0 +1,34 @@ +package org.smartregister.chw.hf; + +import android.app.Activity; +import android.content.Intent; + +import org.junit.Assert; +import org.robolectric.android.controller.ActivityController; +import org.robolectric.shadows.ShadowApplication; + +import timber.log.Timber; + +public abstract class BaseActivityUnitTest extends BaseUnitTest { + + protected void destroyController() { + try { + getActivity().finish(); + getActivityController().pause().stop().destroy(); //destroy controller if we can + + } catch (Exception e) { + Timber.e(e); + } + System.gc(); + } + + protected abstract Activity getActivity(); + + protected abstract ActivityController getActivityController(); + + protected void assertActivityStarted(Activity currActivity, Activity nextActivity) { + Intent expectedIntent = new Intent(currActivity, nextActivity.getClass()); + Intent actual = ShadowApplication.getInstance().getNextStartedActivity(); + Assert.assertEquals(expectedIntent.getComponent(), actual.getComponent()); + } +} diff --git a/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseUnitTest.java b/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseUnitTest.java new file mode 100644 index 000000000..3c318f589 --- /dev/null +++ b/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/BaseUnitTest.java @@ -0,0 +1,14 @@ +package org.smartregister.chw.hf; + +import android.os.Build; + +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@RunWith (RobolectricTestRunner.class) +@Config(application = HealthFacilityApplication.class, sdk = Build.VERSION_CODES.P) +public abstract class BaseUnitTest { + protected static final String DUMMY_USERNAME = "myusername"; + protected static final String DUMMY_PASSWORD = "mypassword"; +} diff --git a/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/activity/LoginActivityTest.java b/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/activity/LoginActivityTest.java new file mode 100644 index 000000000..bb3e5fde7 --- /dev/null +++ b/opensrp-chw-hf/src/test/java/org/smartregister/chw/hf/activity/LoginActivityTest.java @@ -0,0 +1,228 @@ +package org.smartregister.chw.hf.activity; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.view.Menu; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.android.controller.ActivityController; +import org.robolectric.util.ReflectionHelpers; +import org.smartregister.chw.hf.BaseActivityUnitTest; +import org.smartregister.chw.hf.R; +import org.smartregister.view.contract.BaseLoginContract; + +public class LoginActivityTest extends BaseActivityUnitTest { + + private static final String STRING_SETTINGS = "Settings"; + private LoginActivity loginActivity; + private ActivityController controller; + + @Mock + private Menu menu; + + @Mock + private BaseLoginContract.Presenter presenter; + + @Mock + private ProgressDialog progressDialog; + + @Mock + private Button loginButton; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + controller = Robolectric.buildActivity(LoginActivity.class).create().start(); + loginActivity = controller.get(); + } + + @After + public void tearDown() { + destroyController(); + } + + @Test + public void testUserNameEditTextIsInitialized() { + EditText userNameEditText = ReflectionHelpers.getField(loginActivity, "userNameEditText"); + Assert.assertNotNull(userNameEditText); + } + + @Test + public void testPasswordEditTextIsInitialized() { + EditText userPasswordEditText = ReflectionHelpers.getField(loginActivity, "passwordEditText"); + Assert.assertNotNull(userPasswordEditText); + } + + + @Test + public void testShowPasswordCheckBoxIsInitialized() { + CheckBox showPasswordCheckBox = ReflectionHelpers.getField(loginActivity, "showPasswordCheckBox"); + Assert.assertNotNull(showPasswordCheckBox); + } + + @Test + public void testProgressDialogIsInitialized() { + ProgressDialog progressDialog = ReflectionHelpers.getField(loginActivity, "progressDialog"); + Assert.assertNotNull(progressDialog); + } + + + @Test + public void testOnCreateOptionsMenuShouldAddSettingsItem() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + spyActivity.onCreateOptionsMenu(menu); + Mockito.verify(menu).add(STRING_SETTINGS); + } + + + @Test + public void testOnDestroyShouldCallOnDestroyPresenterMethod() { + + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + spyActivity.onDestroy(); + Mockito.verify(presenter).onDestroy(Mockito.anyBoolean()); + } + + @Test + public void testShowProgressShouldShowProgressDialogWhenParamIsTrue() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "progressDialog", progressDialog); + spyActivity.showProgress(true); + Mockito.verify(progressDialog).show(); + } + + @Test + public void testShowProgressShouldDismissProgressDialogWhenParamIsFalse() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "progressDialog", progressDialog); + spyActivity.showProgress(false); + Mockito.verify(progressDialog).dismiss(); + } + + @Test + public void testEnableLoginShouldCallLoginButtonSetClickableMethodWithCorrectParameter() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "loginButton", loginButton); + spyActivity.enableLoginButton(false); + Mockito.verify(loginButton).setClickable(Mockito.anyBoolean()); + } + + @Test + public void testOnEditorActionShouldCallAttemptLoginMethodFromPresenterIfActionIsEnter() { + + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + + Mockito.verify(presenter, Mockito.times(0)).attemptLogin(DUMMY_USERNAME, DUMMY_PASSWORD); + + EditText userNameEditText = Mockito.spy(new EditText(ApplicationProvider.getApplicationContext())); + userNameEditText.setText(DUMMY_USERNAME); + + EditText passwordEditText = Mockito.spy(new EditText(ApplicationProvider.getApplicationContext())); + passwordEditText.setText(DUMMY_PASSWORD); + } + + @Test + public void testOnClickShouldInvokeAttemptLoginPresenterMethodIfLoginButtonClicked() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + spyActivity.onClick(new View(ApplicationProvider.getApplicationContext()));//default + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + EditText editTextUsername = spyActivity.findViewById(R.id.login_user_name_edit_text); + editTextUsername.setText(DUMMY_USERNAME); + EditText editTextPassword = spyActivity.findViewById(R.id.login_password_edit_text); + editTextPassword.setText(DUMMY_PASSWORD); + Button loginButton = spyActivity.findViewById(R.id.login_login_btn); + spyActivity.onClick(loginButton); + Mockito.verify(presenter, Mockito.times(1)).attemptLogin(DUMMY_USERNAME, DUMMY_PASSWORD); + } + + @Test + public void testResetPasswordErrorShouldInvokeSetUsernameErrorWithNull() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + EditText passwordEditText = Mockito.spy(new EditText(ApplicationProvider.getApplicationContext())); + ReflectionHelpers.setField(spyActivity, "passwordEditText", passwordEditText); + spyActivity.resetPaswordError(); + Mockito.verify(passwordEditText).setError(null); + } + + @Test + public void testSetPasswordErrorShouldShowErrorDialogWithCorrectMessage() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + EditText passwordEditText = Mockito.spy(new EditText(ApplicationProvider.getApplicationContext())); + ReflectionHelpers.setField(spyActivity, "passwordEditText", passwordEditText); + Mockito.doNothing().when(spyActivity) + .showErrorDialog(ApplicationProvider.getApplicationContext().getString(R.string.unauthorized)); + spyActivity.setUsernameError(R.string.unauthorized); + Mockito.verify(spyActivity).showErrorDialog(ApplicationProvider.getApplicationContext().getString(R.string.unauthorized)); + } + + @Test + public void testSetUsernameErrorShouldShowErrorDialogWithCorrectMessage() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + EditText userNameEditText = Mockito.spy(new EditText(ApplicationProvider.getApplicationContext())); + ReflectionHelpers.setField(spyActivity, "userNameEditText", userNameEditText); + Mockito.doNothing().when(spyActivity) + .showErrorDialog(ApplicationProvider.getApplicationContext().getString(R.string.unauthorized)); + spyActivity.setPasswordError(R.string.unauthorized); + Mockito.verify(spyActivity).showErrorDialog(ApplicationProvider.getApplicationContext().getString(R.string.unauthorized)); + } + + @Test + public void testResetUsernameErrorShouldInvokeSetUsernameErrorWithNull() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + ReflectionHelpers.setField(spyActivity, "mLoginPresenter", presenter); + EditText userNameEditText = Mockito.spy(new EditText(ApplicationProvider.getApplicationContext())); + ReflectionHelpers.setField(spyActivity, "userNameEditText", userNameEditText); + spyActivity.resetUsernameError(); + Mockito.verify(userNameEditText).setError(null); + } + + @Test + public void testGetActivityContextReturnsCorrectInstance() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + Assert.assertEquals(spyActivity, spyActivity.getActivityContext()); + } + + @Override + protected Activity getActivity() { + return loginActivity; + } + + @Override + protected ActivityController getActivityController() { + return controller; + } + + @Test + public void testGoToHomeRegisterWithRemoteTrue() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + spyActivity.goToHome(true); + assertActivityStarted(spyActivity, new FamilyRegisterActivity()); + } + + @Test + public void testGoToHomeRegisterWithRemote() { + LoginActivity spyActivity = Mockito.spy(loginActivity); + spyActivity.goToHome(false); + assertActivityStarted(spyActivity, new FamilyRegisterActivity()); + } + +} \ No newline at end of file