diff --git a/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt index bebbfe84386..d8093e8b87f 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/home/HomeActivityTest.kt @@ -517,21 +517,6 @@ class HomeActivityTest { } } - @Test - // TODO (#973): Fix HomeActivityTest - @Ignore - fun testHomeActivity_configurationChange_checkSpanForItem0_spanSizeIsThreeOrFour() { - launch(createHomeActivityIntent(internalProfileId)).use { - testCoroutineDispatchers.runCurrent() - onView(isRoot()).perform(orientationLandscape()) - if (context.resources.getBoolean(R.bool.isTablet)) { - onView(withId(R.id.home_recycler_view)).check(hasGridItemCount(4, 0)) - } else { - onView(withId(R.id.home_recycler_view)).check(hasGridItemCount(3, 0)) - } - } - } - @Test fun testHomeActivity_configurationChange_checkSpanForItem4_spanSizeIsOne() { launch(createHomeActivityIntent(internalProfileId)).use { diff --git a/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt b/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt new file mode 100644 index 00000000000..9a5833c634d --- /dev/null +++ b/app/src/test/java/org/oppia/android/app/testing/HomeSpanTest.kt @@ -0,0 +1,184 @@ +package org.oppia.android.app.testing + +import android.app.Application +import android.content.Context +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import androidx.test.core.app.ActivityScenario.launch +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import dagger.Component +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.oppia.android.R +import org.oppia.android.app.activity.ActivityComponent +import org.oppia.android.app.application.ActivityComponentFactory +import org.oppia.android.app.application.ApplicationComponent +import org.oppia.android.app.application.ApplicationInjector +import org.oppia.android.app.application.ApplicationInjectorProvider +import org.oppia.android.app.application.ApplicationModule +import org.oppia.android.app.application.ApplicationStartupListenerModule +import org.oppia.android.app.home.HomeActivity +import org.oppia.android.app.player.state.hintsandsolution.HintsAndSolutionConfigModule +import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.hasGridItemCount +import org.oppia.android.app.shim.IntentFactoryShimModule +import org.oppia.android.app.shim.ViewBindingShimModule +import org.oppia.android.domain.classify.InteractionsModule +import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule +import org.oppia.android.domain.classify.rules.dragAndDropSortInput.DragDropSortInputModule +import org.oppia.android.domain.classify.rules.fractioninput.FractionInputModule +import org.oppia.android.domain.classify.rules.imageClickInput.ImageClickInputModule +import org.oppia.android.domain.classify.rules.itemselectioninput.ItemSelectionInputModule +import org.oppia.android.domain.classify.rules.multiplechoiceinput.MultipleChoiceInputModule +import org.oppia.android.domain.classify.rules.numberwithunits.NumberWithUnitsRuleModule +import org.oppia.android.domain.classify.rules.numericinput.NumericInputRuleModule +import org.oppia.android.domain.classify.rules.ratioinput.RatioInputModule +import org.oppia.android.domain.classify.rules.textinput.TextInputRuleModule +import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule +import org.oppia.android.domain.oppialogger.LogStorageModule +import org.oppia.android.domain.oppialogger.loguploader.LogUploadWorkerModule +import org.oppia.android.domain.oppialogger.loguploader.WorkManagerConfigurationModule +import org.oppia.android.domain.question.QuestionModule +import org.oppia.android.domain.topic.PrimeTopicAssetsControllerModule +import org.oppia.android.testing.TestAccessibilityModule +import org.oppia.android.testing.TestDispatcherModule +import org.oppia.android.testing.TestLogReportingModule +import org.oppia.android.util.caching.testing.CachingTestModule +import org.oppia.android.util.gcsresource.GcsResourceModule +import org.oppia.android.util.logging.LoggerModule +import org.oppia.android.util.logging.firebase.FirebaseLogUploaderModule +import org.oppia.android.util.parser.GlideImageLoaderModule +import org.oppia.android.util.parser.HtmlParserEntityTypeModule +import org.oppia.android.util.parser.ImageParsingModule +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import javax.inject.Inject +import javax.inject.Singleton + +@RunWith(AndroidJUnit4::class) +@LooperMode(LooperMode.Mode.PAUSED) +@Config(application = HomeSpanTest.TestApplication::class) +class HomeSpanTest { + + @Inject + lateinit var context: Context + + private val internalProfileId: Int = 1 + + @Before + fun setUp() { + setUpTestApplicationComponent() + } + + private fun setUpTestApplicationComponent() { + ApplicationProvider.getApplicationContext().inject(this) + } + + @Config(qualifiers = "port") + @Test + fun testHomeSpanTest_checkSpanForItem0_port_hasCorrectSpanCount() { + launch(createHomeActivityIntent(internalProfileId)).use { + onView(withId(R.id.home_recycler_view)) + .check( + hasGridItemCount( + spanCount = 2, + position = 0 + ) + ) + } + } + + @Config(qualifiers = "land") + @Test + fun testHomeSpanTest_checkSpanForItem0_landscape_hasCorrectSpanCount() { + launch(createHomeActivityIntent(internalProfileId)).use { + onView(withId(R.id.home_recycler_view)) + .check( + hasGridItemCount( + spanCount = 3, + position = 0 + ) + ) + } + } + + @Config(qualifiers = "sw600dp-port") + @Test + fun testHomeSpanTest_checkSpanForItem0_port_tablet_hasCorrectSpanCount() { + launch(createHomeActivityIntent(internalProfileId)).use { + onView(withId(R.id.home_recycler_view)) + .check( + hasGridItemCount( + spanCount = 3, + position = 0 + ) + ) + } + } + + @Config(qualifiers = "sw600dp-land") + @Test + fun testHomeSpanTest_checkSpanForItem0_landscape_tablet_hasCorrectSpanCount() { + launch(createHomeActivityIntent(internalProfileId)).use { + onView(withId(R.id.home_recycler_view)) + .check( + hasGridItemCount( + spanCount = 4, + position = 0 + ) + ) + } + } + + private fun createHomeActivityIntent(profileId: Int): Intent { + return HomeActivity.createHomeActivity(context, profileId) + } + + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. + // TODO(#1675): Add NetworkModule once data module is migrated off of Moshi. + @Singleton + @Component( + modules = [ + TestDispatcherModule::class, ApplicationModule::class, + LoggerModule::class, ContinueModule::class, FractionInputModule::class, + ItemSelectionInputModule::class, MultipleChoiceInputModule::class, + NumberWithUnitsRuleModule::class, NumericInputRuleModule::class, TextInputRuleModule::class, + DragDropSortInputModule::class, InteractionsModule::class, GcsResourceModule::class, + GlideImageLoaderModule::class, ImageParsingModule::class, HtmlParserEntityTypeModule::class, + QuestionModule::class, TestLogReportingModule::class, TestAccessibilityModule::class, + ImageClickInputModule::class, LogStorageModule::class, IntentFactoryShimModule::class, + ViewBindingShimModule::class, CachingTestModule::class, RatioInputModule::class, + PrimeTopicAssetsControllerModule::class, ExpirationMetaDataRetrieverModule::class, + ApplicationStartupListenerModule::class, LogUploadWorkerModule::class, + WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class, + FirebaseLogUploaderModule::class + ] + ) + interface TestApplicationComponent : ApplicationComponent { + @Component.Builder + interface Builder : ApplicationComponent.Builder + + fun inject(homeSpanTest: HomeSpanTest) + } + + class TestApplication : Application(), ActivityComponentFactory, ApplicationInjectorProvider { + private val component: TestApplicationComponent by lazy { + DaggerHomeSpanTest_TestApplicationComponent.builder() + .setApplication(this) + .build() as TestApplicationComponent + } + + fun inject(homeSpanTest: HomeSpanTest) { + component.inject(homeSpanTest) + } + + override fun createActivityComponent(activity: AppCompatActivity): ActivityComponent { + return component.getActivityComponentBuilderProvider().get().setActivity(activity).build() + } + + override fun getApplicationInjector(): ApplicationInjector = component + } +}