diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 78ac8495b48..1e435dfc707 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -11,15 +11,16 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/OppiaTheme">
-
-
+
+
-
+
+
@@ -34,4 +35,4 @@
android:theme="@style/SplashScreenTheme" />
-
+
\ No newline at end of file
diff --git a/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt b/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt
index 1038aecf0ba..e1dbd77de7d 100644
--- a/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt
+++ b/app/src/main/java/org/oppia/app/activity/ActivityComponent.kt
@@ -10,6 +10,7 @@ import org.oppia.app.player.exploration.ExplorationActivity
import org.oppia.app.topic.conceptcard.testing.ConceptCardFragmentTestActivity
import org.oppia.app.player.state.testing.StateFragmentTestActivity
import org.oppia.app.profile.ProfileActivity
+import org.oppia.app.story.StoryActivity
import org.oppia.app.testing.BindableAdapterTestActivity
import org.oppia.app.topic.TopicActivity
import org.oppia.app.topic.questionplayer.QuestionPlayerActivity
@@ -27,13 +28,14 @@ interface ActivityComponent {
fun getFragmentComponentBuilderProvider(): Provider
+ fun inject(audioFragmentTestActivity: AudioFragmentTestActivity)
fun inject(bindableAdapterTestActivity: BindableAdapterTestActivity)
+ fun inject(conceptCardFragmentTestActivity: ConceptCardFragmentTestActivity)
fun inject(explorationActivity: ExplorationActivity)
fun inject(homeActivity: HomeActivity)
- fun inject(conceptCardFragmentTestActivity: ConceptCardFragmentTestActivity)
+ fun inject(profileActivity: ProfileActivity)
fun inject(questionPlayerActivity: QuestionPlayerActivity)
- fun inject(topicActivity: TopicActivity)
- fun inject(audioFragmentTestActivity: AudioFragmentTestActivity)
fun inject(stateFragmentTestActivity: StateFragmentTestActivity)
- fun inject(profileActivity: ProfileActivity)
+ fun inject(storyActivity: StoryActivity)
+ fun inject(topicActivity: TopicActivity)
}
diff --git a/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt b/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt
index e982ef2160f..885957b3028 100644
--- a/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt
+++ b/app/src/main/java/org/oppia/app/fragment/FragmentComponent.kt
@@ -10,6 +10,7 @@ import org.oppia.app.player.audio.AudioFragment
import org.oppia.app.profile.AddProfileFragment
import org.oppia.app.profile.AdminAuthFragment
import org.oppia.app.profile.ProfileChooserFragment
+import org.oppia.app.story.StoryFragment
import org.oppia.app.testing.BindableAdapterTestFragment
import org.oppia.app.topic.TopicFragment
import org.oppia.app.topic.conceptcard.ConceptCardFragment
@@ -25,23 +26,26 @@ import org.oppia.app.topic.train.TopicTrainFragment
interface FragmentComponent {
@Subcomponent.Builder
interface Builder {
- @BindsInstance fun setFragment(fragment: Fragment): Builder
+ @BindsInstance
+ fun setFragment(fragment: Fragment): Builder
+
fun build(): FragmentComponent
}
+ fun inject(addProfileFragment: AddProfileFragment)
+ fun inject(adminAuthFragment: AdminAuthFragment)
fun inject(audioFragment: AudioFragment)
+ fun inject(bindableAdapterTestFragment: BindableAdapterTestFragment)
fun inject(conceptCardFragment: ConceptCardFragment)
fun inject(explorationFragment: ExplorationFragment)
fun inject(homeFragment: HomeFragment)
+ fun inject(profileChooserFragment: ProfileChooserFragment)
fun inject(questionPlayerFragment: QuestionPlayerFragment)
fun inject(stateFragment: StateFragment)
- fun inject(bindableAdapterTestFragment: BindableAdapterTestFragment)
+ fun inject(storyFragment: StoryFragment)
fun inject(topicFragment: TopicFragment)
fun inject(topicOverviewFragment: TopicOverviewFragment)
fun inject(topicPlayFragment: TopicPlayFragment)
fun inject(topicReviewFragment: TopicReviewFragment)
fun inject(topicTrainFragment: TopicTrainFragment)
- fun inject(profileChooserFragment: ProfileChooserFragment)
- fun inject(adminAuthFragment: AdminAuthFragment)
- fun inject(addProfileFragment: AddProfileFragment)
}
diff --git a/app/src/main/java/org/oppia/app/story/StoryActivity.kt b/app/src/main/java/org/oppia/app/story/StoryActivity.kt
new file mode 100644
index 00000000000..63e9178f5c9
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/story/StoryActivity.kt
@@ -0,0 +1,29 @@
+package org.oppia.app.story
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import org.oppia.app.activity.InjectableAppCompatActivity
+import javax.inject.Inject
+
+/** Activity for stories. */
+class StoryActivity : InjectableAppCompatActivity() {
+ @Inject lateinit var storyActivityPresenter: StoryActivityPresenter
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ activityComponent.inject(this)
+ storyActivityPresenter.handleOnCreate()
+ }
+
+ companion object {
+ const val STORY_ACTIVITY_STORY_ID_ARGUMENT_KEY = "StoryActivity.story_id"
+
+ /** Returns a new [Intent] to route to [StoryActivity] for a specified story ID. */
+ fun createStoryActivityIntent(context: Context, storyId: String): Intent {
+ val intent = Intent(context, StoryActivity::class.java)
+ intent.putExtra(STORY_ACTIVITY_STORY_ID_ARGUMENT_KEY, storyId)
+ return intent
+ }
+ }
+}
diff --git a/app/src/main/java/org/oppia/app/story/StoryActivityPresenter.kt b/app/src/main/java/org/oppia/app/story/StoryActivityPresenter.kt
new file mode 100644
index 00000000000..e867d336650
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/story/StoryActivityPresenter.kt
@@ -0,0 +1,24 @@
+package org.oppia.app.story
+
+import androidx.appcompat.app.AppCompatActivity
+import org.oppia.app.R
+import org.oppia.app.activity.ActivityScope
+import javax.inject.Inject
+
+/** The presenter for [StoryActivity]. */
+@ActivityScope
+class StoryActivityPresenter @Inject constructor(private val activity: AppCompatActivity) {
+ fun handleOnCreate() {
+ activity.setContentView(R.layout.story_activity)
+ if (getStoryFragment() == null) {
+ activity.supportFragmentManager.beginTransaction().add(
+ R.id.story_fragment_placeholder,
+ StoryFragment()
+ ).commitNow()
+ }
+ }
+
+ private fun getStoryFragment(): StoryFragment? {
+ return activity.supportFragmentManager.findFragmentById(R.id.story_fragment_placeholder) as StoryFragment?
+ }
+}
diff --git a/app/src/main/java/org/oppia/app/story/StoryFragment.kt b/app/src/main/java/org/oppia/app/story/StoryFragment.kt
new file mode 100644
index 00000000000..6938d216a6d
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/story/StoryFragment.kt
@@ -0,0 +1,24 @@
+package org.oppia.app.story
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import org.oppia.app.fragment.InjectableFragment
+import javax.inject.Inject
+
+/** Fragment that displays story with chapter list. */
+class StoryFragment : InjectableFragment() {
+ @Inject
+ lateinit var storyFragmentPresenter: StoryFragmentPresenter
+
+ override fun onAttach(context: Context?) {
+ super.onAttach(context)
+ fragmentComponent.inject(this)
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return storyFragmentPresenter.handleCreateView(inflater, container)
+ }
+}
diff --git a/app/src/main/java/org/oppia/app/story/StoryFragmentPresenter.kt b/app/src/main/java/org/oppia/app/story/StoryFragmentPresenter.kt
new file mode 100644
index 00000000000..5d9404ca29a
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/story/StoryFragmentPresenter.kt
@@ -0,0 +1,23 @@
+package org.oppia.app.story
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import org.oppia.app.databinding.StoryFragmentBinding
+import org.oppia.app.fragment.FragmentScope
+import javax.inject.Inject
+
+/** The presenter for [StoryFragment]. */
+@FragmentScope
+class StoryFragmentPresenter @Inject constructor(
+ private val fragment: Fragment
+) {
+ fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
+ val binding = StoryFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
+ binding.let {
+ it.lifecycleOwner = fragment
+ }
+ return binding.root
+ }
+}
diff --git a/app/src/main/java/org/oppia/app/topic/RouteToStoryListener.kt b/app/src/main/java/org/oppia/app/topic/RouteToStoryListener.kt
new file mode 100755
index 00000000000..efd5b10d063
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/topic/RouteToStoryListener.kt
@@ -0,0 +1,6 @@
+package org.oppia.app.topic
+
+/** Listener for when an [TopicActivity] should route to a [StoryActivity]. */
+interface RouteToStoryListener {
+ fun routeToStory(storyId: String)
+}
diff --git a/app/src/main/java/org/oppia/app/topic/TopicActivity.kt b/app/src/main/java/org/oppia/app/topic/TopicActivity.kt
index 0b0ad44d29e..b4bb533aa44 100644
--- a/app/src/main/java/org/oppia/app/topic/TopicActivity.kt
+++ b/app/src/main/java/org/oppia/app/topic/TopicActivity.kt
@@ -2,13 +2,15 @@ package org.oppia.app.topic
import android.os.Bundle
import org.oppia.app.activity.InjectableAppCompatActivity
+import org.oppia.app.story.StoryActivity
import org.oppia.app.topic.conceptcard.ConceptCardFragment
import org.oppia.app.topic.questionplayer.QuestionPlayerActivity
import javax.inject.Inject
/** The activity for tabs in Topic. */
+
class TopicActivity : InjectableAppCompatActivity(), RouteToQuestionPlayerListener, RouteToConceptCardListener,
- RouteToTopicPlayListener {
+ RouteToTopicPlayListener, RouteToStoryListener {
@Inject
lateinit var topicActivityPresenter: TopicActivityPresenter
@@ -22,6 +24,10 @@ class TopicActivity : InjectableAppCompatActivity(), RouteToQuestionPlayerListen
startActivity(QuestionPlayerActivity.createQuestionPlayerActivityIntent(this, skillIdList))
}
+ override fun routeToStory(storyId: String) {
+ startActivity(StoryActivity.createStoryActivityIntent(this, storyId))
+ }
+
override fun routeToTopicPlayFragment() {
// TODO(#135): Change to play tab in this function.
}
diff --git a/app/src/main/java/org/oppia/app/topic/TopicFragmentPresenter.kt b/app/src/main/java/org/oppia/app/topic/TopicFragmentPresenter.kt
index 24e7b205070..4976ed43017 100644
--- a/app/src/main/java/org/oppia/app/topic/TopicFragmentPresenter.kt
+++ b/app/src/main/java/org/oppia/app/topic/TopicFragmentPresenter.kt
@@ -8,7 +8,7 @@ import org.oppia.app.databinding.TopicFragmentBinding
import org.oppia.app.fragment.FragmentScope
import javax.inject.Inject
-/** The controller for [TopicFragment]. */
+/** The presenter for [TopicFragment]. */
@FragmentScope
class TopicFragmentPresenter @Inject constructor(
private val fragment: Fragment
diff --git a/app/src/main/java/org/oppia/app/topic/play/StorySummaryAdapter.kt b/app/src/main/java/org/oppia/app/topic/play/StorySummaryAdapter.kt
new file mode 100644
index 00000000000..99de7512d37
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/topic/play/StorySummaryAdapter.kt
@@ -0,0 +1,46 @@
+package org.oppia.app.topic.play
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.databinding.DataBindingUtil
+import androidx.databinding.library.baseAdapters.BR
+import androidx.recyclerview.widget.RecyclerView
+import org.oppia.app.R
+import org.oppia.app.databinding.TopicPlayStorySummaryBinding
+import org.oppia.app.model.StorySummary
+
+// TODO(#216): Make use of generic data-binding-enabled RecyclerView adapter.
+/** Adapter to bind StorySummary to [RecyclerView] inside [TopicPlayFragment]. */
+class StorySummaryAdapter(
+ private var storyList: MutableList,
+ private val storySummarySelector: StorySummarySelector
+) :
+ RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StorySummaryViewHolder {
+ val storySummaryListItemBinding = DataBindingUtil.inflate(
+ LayoutInflater.from(parent.context),
+ R.layout.topic_play_story_summary, parent,
+ /* attachToRoot= */ false
+ )
+ return StorySummaryViewHolder(storySummaryListItemBinding)
+ }
+
+ override fun onBindViewHolder(storySummaryViewHolder: StorySummaryViewHolder, i: Int) {
+ storySummaryViewHolder.bind(storyList[i], i)
+ }
+
+ override fun getItemCount(): Int {
+ return storyList.size
+ }
+
+ inner class StorySummaryViewHolder(private val binding: TopicPlayStorySummaryBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ internal fun bind(storySummary: StorySummary, @Suppress("UNUSED_PARAMETER") position: Int) {
+ binding.setVariable(BR.storySummary, storySummary)
+ binding.root.setOnClickListener {
+ storySummarySelector.selectedStorySummary(storySummary)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/org/oppia/app/topic/play/StorySummarySelector.kt b/app/src/main/java/org/oppia/app/topic/play/StorySummarySelector.kt
new file mode 100644
index 00000000000..f7974b3ae90
--- /dev/null
+++ b/app/src/main/java/org/oppia/app/topic/play/StorySummarySelector.kt
@@ -0,0 +1,8 @@
+package org.oppia.app.topic.play
+
+import org.oppia.app.model.StorySummary
+
+/** Interface to transfer the selected story summary to [TopicPlayFragmentPresenter]. */
+interface StorySummarySelector {
+ fun selectedStorySummary(storySummary: StorySummary)
+}
diff --git a/app/src/main/java/org/oppia/app/topic/play/TopicPlayFragmentPresenter.kt b/app/src/main/java/org/oppia/app/topic/play/TopicPlayFragmentPresenter.kt
index fd863ef33a0..3c989d6c1b7 100644
--- a/app/src/main/java/org/oppia/app/topic/play/TopicPlayFragmentPresenter.kt
+++ b/app/src/main/java/org/oppia/app/topic/play/TopicPlayFragmentPresenter.kt
@@ -3,21 +3,73 @@ package org.oppia.app.topic.play
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.Observer
+import androidx.lifecycle.Transformations
import org.oppia.app.databinding.TopicPlayFragmentBinding
import org.oppia.app.fragment.FragmentScope
+import org.oppia.app.model.StorySummary
+import org.oppia.app.model.Topic
+import org.oppia.app.topic.RouteToStoryListener
+import org.oppia.domain.topic.TEST_TOPIC_ID_0
+import org.oppia.domain.topic.TopicController
+import org.oppia.util.data.AsyncResult
+import org.oppia.util.logging.Logger
import javax.inject.Inject
/** The presenter for [TopicPlayFragment]. */
@FragmentScope
class TopicPlayFragmentPresenter @Inject constructor(
- private val fragment: Fragment
-) {
+ activity: AppCompatActivity,
+ private val fragment: Fragment,
+ private val logger: Logger,
+ private val topicController: TopicController
+) : StorySummarySelector {
+
+ private val routeToStoryListener = activity as RouteToStoryListener
+
+ private lateinit var binding: TopicPlayFragmentBinding
+
fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
- val binding = TopicPlayFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
+ binding = TopicPlayFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
+
binding.let {
it.lifecycleOwner = fragment
}
+ subscribeToTopicLiveData()
return binding.root
}
+
+ private val topicLiveData: LiveData by lazy { getTopicList() }
+
+ // TODO(#135): Get this topic-id or get storyList from [StoryFragment].
+ private val topicResultLiveData: LiveData> by lazy {
+ topicController.getTopic(TEST_TOPIC_ID_0)
+ }
+
+ private fun subscribeToTopicLiveData() {
+ topicLiveData.observe(fragment, Observer {
+ val storySummaryAdapter = StorySummaryAdapter(it.storyList, this as StorySummarySelector)
+ binding.storySummaryRecyclerView.apply {
+ adapter = storySummaryAdapter
+ }
+ })
+ }
+
+ private fun getTopicList(): LiveData {
+ return Transformations.map(topicResultLiveData, ::processTopicResult)
+ }
+
+ private fun processTopicResult(topic: AsyncResult): Topic {
+ if (topic.isFailure()) {
+ logger.e("TopicPlayFragment", "Failed to retrieve topic", topic.getErrorOrNull()!!)
+ }
+ return topic.getOrDefault(Topic.getDefaultInstance())
+ }
+
+ override fun selectedStorySummary(storySummary: StorySummary) {
+ routeToStoryListener.routeToStory(storySummary.storyId)
+ }
}
diff --git a/app/src/main/res/drawable/circular_progress.xml b/app/src/main/res/drawable/circular_progress.xml
new file mode 100755
index 00000000000..def50eeaa3e
--- /dev/null
+++ b/app/src/main/res/drawable/circular_progress.xml
@@ -0,0 +1,40 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml b/app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml
new file mode 100644
index 00000000000..b7de895ec0f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_up_black_24dp.xml b/app/src/main/res/drawable/ic_keyboard_arrow_up_black_24dp.xml
new file mode 100644
index 00000000000..16a9974a1a7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_keyboard_arrow_up_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/story_activity.xml b/app/src/main/res/layout/story_activity.xml
new file mode 100644
index 00000000000..4c2d686433c
--- /dev/null
+++ b/app/src/main/res/layout/story_activity.xml
@@ -0,0 +1,8 @@
+
+
diff --git a/app/src/main/res/layout/story_fragment.xml b/app/src/main/res/layout/story_fragment.xml
new file mode 100644
index 00000000000..e9b0824c1b7
--- /dev/null
+++ b/app/src/main/res/layout/story_fragment.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/topic_play_fragment.xml b/app/src/main/res/layout/topic_play_fragment.xml
index e9b0824c1b7..6a6aaba035e 100644
--- a/app/src/main/res/layout/topic_play_fragment.xml
+++ b/app/src/main/res/layout/topic_play_fragment.xml
@@ -1,18 +1,20 @@
-
-
+
+ app:layout_constraintTop_toTopOf="parent" />
diff --git a/app/src/main/res/layout/topic_play_story_summary.xml b/app/src/main/res/layout/topic_play_story_summary.xml
new file mode 100644
index 00000000000..27dc2d14906
--- /dev/null
+++ b/app/src/main/res/layout/topic_play_story_summary.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bb9d73eb258..f33f78064f6 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -25,6 +25,14 @@
LEARN AGAIN
See More
(%s MB)
+
+ -
+ 1 Chapter
+
+ -
+ %d Chapters
+
+
-
1 Story
diff --git a/app/src/sharedTest/java/org/oppia/app/topic/play/TopicPlayFragmentTest.kt b/app/src/sharedTest/java/org/oppia/app/topic/play/TopicPlayFragmentTest.kt
index 7c6f9a4b465..87aeed9e9a1 100644
--- a/app/src/sharedTest/java/org/oppia/app/topic/play/TopicPlayFragmentTest.kt
+++ b/app/src/sharedTest/java/org/oppia/app/topic/play/TopicPlayFragmentTest.kt
@@ -2,21 +2,37 @@ package org.oppia.app.topic.play
import android.app.Application
import android.content.Context
-import androidx.test.core.app.ActivityScenario
+import android.content.res.Configuration
import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
-import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.intent.Intents
+import androidx.test.espresso.intent.Intents.intended
+import androidx.test.espresso.intent.matcher.IntentMatchers
+import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
+import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.rule.ActivityTestRule
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.CoroutineDispatcher
+import org.hamcrest.Matchers.containsString
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.oppia.app.R
+import org.oppia.app.recyclerview.RecyclerViewMatcher.Companion.atPosition
+import org.oppia.app.story.StoryActivity
import org.oppia.app.topic.TopicActivity
+import org.oppia.app.topic.questionplayer.QuestionPlayerActivity
import org.oppia.util.threading.BackgroundDispatcher
import org.oppia.util.threading.BlockingDispatcher
import javax.inject.Singleton
@@ -25,11 +41,81 @@ import javax.inject.Singleton
@RunWith(AndroidJUnit4::class)
class TopicPlayFragmentTest {
+ // TODO(#137): Add following test-cases once story-progress function is implemented and expandable list is introduced.
+ // - Story progress is displayed correctly.
+ // - Click on arrow to show and hide expandable list is working correctly.
+ // - Expandable list is showing correct chapter names.
+ // - Upon configuration change expanded list should remain expanded.
+ // - Click on story-title or entire item should open [StoryActivity].
+ // - Click on chapter in expandable list should start exploration.
+
+ @get:Rule
+ var activityTestRule: ActivityTestRule = ActivityTestRule(
+ TopicActivity::class.java, /* initialTouchMode= */ true, /* launchActivity= */ false
+ )
+ private var storyId = "test_story_id_0"
+
+ @Before
+ fun setUp() {
+ Intents.init()
+ }
+
@Test
- fun testTopicPlayFragment_loadFragment_textIsDisplayed() {
- ActivityScenario.launch(TopicActivity::class.java).use {
- onView(withId(R.id.dummy_text_view)).check(matches(withText("This is dummy TextView for testing")))
- }
+ fun testTopicPlayFragment_loadFragmentWithTopicTestId0_storyName_isCorrect() {
+ activityTestRule.launchActivity(null)
+ onView(
+ atPosition(
+ R.id.story_summary_recycler_view,
+ 0
+ )
+ ).check(matches(hasDescendant(withText(containsString("First Story")))))
+ }
+
+ @Test
+ fun testTopicPlayFragment_loadFragmentWithTopicTestId0_chapterCountTextSingle_isCorrect() {
+ activityTestRule.launchActivity(null)
+ onView(
+ atPosition(
+ R.id.story_summary_recycler_view,
+ 0
+ )
+ ).check(matches(hasDescendant(withText(containsString("1 Chapter")))))
+ }
+
+ @Test
+ fun testTopicPlayFragment_loadFragmentWithTopicTestId0_chapterCountTextMultiple_isCorrect() {
+ activityTestRule.launchActivity(null)
+ onView(
+ atPosition(
+ R.id.story_summary_recycler_view,
+ 1
+ )
+ ).check(matches(hasDescendant(withText(containsString("3 Chapters")))))
+ }
+
+ @Test
+ fun testTopicPlayFragment_loadFragmentWithTopicTestId0_configurationChange_storyName_isCorrect() {
+ activityTestRule.launchActivity(null)
+ activityTestRule.activity.requestedOrientation = Configuration.ORIENTATION_LANDSCAPE
+ onView(
+ atPosition(
+ R.id.story_summary_recycler_view,
+ 0
+ )
+ ).check(matches(hasDescendant(withText(containsString("First Story")))))
+ }
+
+ @Test
+ fun testTopicPlayFragment_loadFragmentWithTopicTestId0_clickStoryItem_opensStoryActivityWithCorrectIntent() {
+ activityTestRule.launchActivity(null)
+ onView(atPosition(R.id.story_summary_recycler_view, 0)).perform(click())
+ intended(hasComponent(StoryActivity::class.java.name))
+ intended(hasExtra(StoryActivity.STORY_ACTIVITY_STORY_ID_ARGUMENT_KEY, storyId))
+ }
+
+ @After
+ fun tearDown() {
+ Intents.release()
}
@Module