feat: route board and card taps to detail screens
This commit is contained in:
@@ -11,6 +11,9 @@ import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.longClick
|
||||
import androidx.test.espresso.action.ViewActions.replaceText
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.intent.Intents
|
||||
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||
import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra
|
||||
import androidx.test.espresso.matcher.RootMatchers.isDialog
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
@@ -53,12 +56,14 @@ class BoardDetailFlowTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
originalLocale = Locale.getDefault()
|
||||
Intents.init()
|
||||
defaultDataSource = FakeBoardDetailDataSource(initialDetail = detailOneList())
|
||||
BoardDetailActivity.testDataSourceFactory = { defaultDataSource }
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
Intents.release()
|
||||
BoardDetailActivity.testDataSourceFactory = null
|
||||
originalLocale?.let { Locale.setDefault(it) }
|
||||
}
|
||||
@@ -245,6 +250,29 @@ class BoardDetailFlowTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cardTapNavigatesToCardPlaceholderWithExtras() {
|
||||
launchBoardDetail()
|
||||
|
||||
onView(withText("Card 1")).perform(click())
|
||||
|
||||
Intents.intended(hasComponent(CardDetailPlaceholderActivity::class.java.name))
|
||||
Intents.intended(hasExtra(CardDetailPlaceholderActivity.EXTRA_CARD_ID, "card-1"))
|
||||
Intents.intended(hasExtra(CardDetailPlaceholderActivity.EXTRA_CARD_TITLE, "Card 1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cardTapBlankTitle_usesCardFallbackInPlaceholderExtra() {
|
||||
defaultDataSource.currentDetail = detailWithCardTitle(" ")
|
||||
launchBoardDetail()
|
||||
|
||||
onView(withId(R.id.cardItemRoot)).perform(click())
|
||||
|
||||
Intents.intended(hasComponent(CardDetailPlaceholderActivity::class.java.name))
|
||||
Intents.intended(hasExtra(CardDetailPlaceholderActivity.EXTRA_CARD_ID, "card-1"))
|
||||
Intents.intended(hasExtra(CardDetailPlaceholderActivity.EXTRA_CARD_TITLE, "Card"))
|
||||
}
|
||||
|
||||
private fun launchBoardDetail(): ActivityScenario<BoardDetailActivity> {
|
||||
val intent = Intent(
|
||||
androidx.test.core.app.ApplicationProvider.getApplicationContext(),
|
||||
@@ -353,5 +381,24 @@ class BoardDetailFlowTest {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun detailWithCardTitle(title: String): BoardDetail {
|
||||
return detailOneList().copy(
|
||||
lists = listOf(
|
||||
BoardListDetail(
|
||||
id = "list-1",
|
||||
title = "To Do",
|
||||
cards = listOf(
|
||||
BoardCardSummary(
|
||||
id = "card-1",
|
||||
title = title,
|
||||
tags = emptyList(),
|
||||
dueAtEpochMillis = null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class BoardsFlowTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun boardTapNavigatesToDetailPlaceholderWithExtras() {
|
||||
fun boardTapNavigatesToBoardDetailActivity() {
|
||||
MainActivity.dependencies.apiClientFactory = {
|
||||
FakeBoardsApiClient(
|
||||
boards = mutableListOf(BoardSummary("1", "Alpha")),
|
||||
@@ -58,9 +58,9 @@ class BoardsFlowTest {
|
||||
|
||||
onView(withText("Alpha")).perform(click())
|
||||
|
||||
Intents.intended(hasComponent(BoardDetailPlaceholderActivity::class.java.name))
|
||||
Intents.intended(hasExtra(BoardDetailPlaceholderActivity.EXTRA_BOARD_ID, "1"))
|
||||
Intents.intended(hasExtra(BoardDetailPlaceholderActivity.EXTRA_BOARD_TITLE, "Alpha"))
|
||||
Intents.intended(hasComponent(space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailActivity::class.java.name))
|
||||
Intents.intended(hasExtra(space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailActivity.EXTRA_BOARD_ID, "1"))
|
||||
Intents.intended(hasExtra(space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailActivity.EXTRA_BOARD_TITLE, "Alpha"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,8 +79,8 @@ class BoardsFlowTest {
|
||||
onView(withId(R.id.useTemplateChip)).perform(click())
|
||||
onView(withId(android.R.id.button1)).inRoot(isDialog()).perform(click())
|
||||
|
||||
Intents.intended(hasComponent(BoardDetailPlaceholderActivity::class.java.name))
|
||||
Intents.intended(hasExtra(BoardDetailPlaceholderActivity.EXTRA_BOARD_TITLE, "Roadmap"))
|
||||
Intents.intended(hasComponent(space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailActivity::class.java.name))
|
||||
Intents.intended(hasExtra(space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailActivity.EXTRA_BOARD_TITLE, "Roadmap"))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/Theme.Kanbn4Droid">
|
||||
<activity
|
||||
android:name=".BoardDetailPlaceholderActivity"
|
||||
android:name=".CardDetailPlaceholderActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".boarddetail.BoardDetailActivity"
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package space.hackenslacker.kanbn4droid.app
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
class BoardDetailPlaceholderActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_board_detail_placeholder)
|
||||
|
||||
val boardTitle = intent.getStringExtra(EXTRA_BOARD_TITLE).orEmpty()
|
||||
val boardId = intent.getStringExtra(EXTRA_BOARD_ID).orEmpty()
|
||||
|
||||
val titleView: TextView = findViewById(R.id.boardDetailPlaceholderTitle)
|
||||
titleView.text = getString(R.string.board_detail_placeholder_title, boardTitle, boardId)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_BOARD_ID = "extra_board_id"
|
||||
const val EXTRA_BOARD_TITLE = "extra_board_title"
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import space.hackenslacker.kanbn4droid.app.boards.BoardsRepository
|
||||
import space.hackenslacker.kanbn4droid.app.boards.BoardsUiEvent
|
||||
import space.hackenslacker.kanbn4droid.app.boards.BoardsUiState
|
||||
import space.hackenslacker.kanbn4droid.app.boards.BoardsViewModel
|
||||
import space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailActivity
|
||||
|
||||
class BoardsActivity : AppCompatActivity() {
|
||||
private lateinit var sessionStore: SessionStore
|
||||
@@ -245,9 +246,9 @@ class BoardsActivity : AppCompatActivity() {
|
||||
|
||||
private fun navigateToBoard(board: BoardSummary) {
|
||||
startActivity(
|
||||
Intent(this, BoardDetailPlaceholderActivity::class.java)
|
||||
.putExtra(BoardDetailPlaceholderActivity.EXTRA_BOARD_ID, board.id)
|
||||
.putExtra(BoardDetailPlaceholderActivity.EXTRA_BOARD_TITLE, board.title),
|
||||
Intent(this, BoardDetailActivity::class.java)
|
||||
.putExtra(BoardDetailActivity.EXTRA_BOARD_ID, board.id)
|
||||
.putExtra(BoardDetailActivity.EXTRA_BOARD_TITLE, board.title),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package space.hackenslacker.kanbn4droid.app
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
class CardDetailPlaceholderActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_card_detail_placeholder)
|
||||
|
||||
val cardId = intent.getStringExtra(EXTRA_CARD_ID).orEmpty()
|
||||
val cardTitle = intent.getStringExtra(EXTRA_CARD_TITLE).orEmpty()
|
||||
|
||||
val titleView: TextView = findViewById(R.id.cardDetailPlaceholderTitle)
|
||||
titleView.text = "$cardTitle\n(id: $cardId)"
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_CARD_ID = "extra_card_id"
|
||||
const val EXTRA_CARD_TITLE = "extra_card_title"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package space.hackenslacker.kanbn4droid.app.boarddetail
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
@@ -17,6 +18,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.launch
|
||||
import space.hackenslacker.kanbn4droid.app.MainActivity
|
||||
import space.hackenslacker.kanbn4droid.app.CardDetailPlaceholderActivity
|
||||
import space.hackenslacker.kanbn4droid.app.R
|
||||
import space.hackenslacker.kanbn4droid.app.auth.ApiKeyStore
|
||||
import space.hackenslacker.kanbn4droid.app.auth.HttpKanbnApiClient
|
||||
@@ -157,7 +159,21 @@ class BoardDetailActivity : AppCompatActivity() {
|
||||
viewModel.events.collect { event ->
|
||||
when (event) {
|
||||
is BoardDetailUiEvent.NavigateToCardPlaceholder -> {
|
||||
Snackbar.make(pager, getString(R.string.board_detail_card_detail_coming_soon), Snackbar.LENGTH_SHORT).show()
|
||||
val cardTitle = viewModel.uiState.value.boardDetail
|
||||
?.lists
|
||||
.orEmpty()
|
||||
.asSequence()
|
||||
.flatMap { list -> list.cards.asSequence() }
|
||||
.firstOrNull { card -> card.id == event.cardId }
|
||||
?.title
|
||||
.orEmpty()
|
||||
.trim()
|
||||
.ifBlank { "Card" }
|
||||
startActivity(
|
||||
Intent(this@BoardDetailActivity, CardDetailPlaceholderActivity::class.java)
|
||||
.putExtra(CardDetailPlaceholderActivity.EXTRA_CARD_ID, event.cardId)
|
||||
.putExtra(CardDetailPlaceholderActivity.EXTRA_CARD_TITLE, cardTitle),
|
||||
)
|
||||
}
|
||||
|
||||
is BoardDetailUiEvent.ShowServerError -> {
|
||||
|
||||
30
app/src/main/res/layout/activity_card_detail_placeholder.xml
Normal file
30
app/src/main/res/layout/activity_card_detail_placeholder.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardDetailPlaceholderTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardDetailPlaceholderSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/board_detail_card_detail_coming_soon"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cardDetailPlaceholderTitle" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Reference in New Issue
Block a user