Skip to content

Commit d0f8133

Browse files
committed
refactor: Refactor note save change logic and update UI tests
- Introduce `ShowCheckSaveChangeDialog` action to explicitly handle the display of the save confirmation dialog. - Update `NoteViewModel` to separate the logic for checking changes from the logic for showing the save dialog, moving navigation into `showSaveChangesDialog`. - Refactor `BaseTestCase` to use `inline` functions and expose `commonDialog` to improve test performance and accessibility. - Update `CreateNoteWhileSelectedTestCase` to follow the new UI navigation and assertion flow, ensuring the note state is preserved when canceling the save dialog. - Update `NoteDetail` to trigger the new `ShowCheckSaveChangeDialog` action.
1 parent af298d2 commit d0f8133

File tree

5 files changed

+30
-30
lines changed

5 files changed

+30
-30
lines changed

core/presentation/src/commonMain/kotlin/com/softartdev/notedelight/presentation/note/NoteResult.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ sealed interface NoteAction {
1515
data object Edit : NoteAction
1616
data object Delete : NoteAction
1717
data class CheckSaveChange(val title: String, val text: CharSequence) : NoteAction
18+
data class ShowCheckSaveChangeDialog(val title: String, val text: CharSequence) : NoteAction
1819
}

core/presentation/src/commonMain/kotlin/com/softartdev/notedelight/presentation/note/NoteViewModel.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class NoteViewModel(
6565
is NoteAction.Edit -> editTitle()
6666
is NoteAction.Delete -> subscribeToDeleteNote()
6767
is NoteAction.CheckSaveChange -> checkSaveChange(title = action.title, text = action.text.toString())
68+
is NoteAction.ShowCheckSaveChangeDialog -> showSaveChangesDialog(title = action.title, text = action.text.toString())
6869
}
6970

7071
private fun createOrLoadNote() = when (noteId) {
@@ -154,10 +155,7 @@ class NoteViewModel(
154155
val changed: Boolean = isChanged(noteId, noteTitle, text)
155156
val empty: Boolean = isEmpty(noteId)
156157
when {
157-
changed -> {
158-
router.navigate(route = AppNavGraph.SaveChangesDialog)
159-
subscribeToSaveNote(title, text)
160-
}
158+
changed -> showSaveChangesDialog(title, text)
161159
empty -> deleteNoteForResult()
162160
else -> adaptiveNavigateBack()
163161
}
@@ -168,9 +166,10 @@ class NoteViewModel(
168166
}
169167
}
170168

171-
private fun subscribeToSaveNote(title: String?, text: String) = viewModelScope.launch {
169+
private fun showSaveChangesDialog(title: String?, text: String) = viewModelScope.launch {
172170
mutableStateFlow.update(NoteResult::showLoading)
173171
try {
172+
router.navigate(route = AppNavGraph.SaveChangesDialog)
174173
logger.d { "Subscribe to save note dialog channel" }
175174
val doSave: Boolean? = withContext(coroutineDispatchers.io) {
176175
SaveNoteUseCase.dialogChannel.receive()

ui/shared/src/commonMain/kotlin/com/softartdev/notedelight/ui/main/NoteDetail.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fun NoteDetail(
9393
}
9494
LaunchedEffect(checkSaveChangeChannel) {
9595
checkSaveChangeChannel.receiveAsFlow().collect {
96-
onAction(NoteAction.CheckSaveChange(titleState.value, textState.text))
96+
onAction(NoteAction.ShowCheckSaveChangeDialog(titleState.value, textState.text))
9797
}
9898
}
9999
NoteDetailBody(

ui/test/src/commonMain/kotlin/com/softartdev/notedelight/ui/BaseTestCase.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,35 @@ import com.softartdev.notedelight.ui.screen.dialog.LanguageDialog
1818

1919
abstract class BaseTestCase(val composeUiTest: ComposeUiTest) {
2020

21-
private val commonDialog: CommonDialog = CommonDialogImpl(composeUiTest)
21+
val commonDialog: CommonDialog = CommonDialogImpl(composeUiTest)
2222

23-
suspend fun signInScreen(block: suspend SignInScreen.() -> Unit) =
23+
suspend inline fun signInScreen(block: suspend SignInScreen.() -> Unit) =
2424
SignInScreen(composeUiTest).block()
2525

26-
suspend fun mainTestScreen(block: suspend MainTestScreen.() -> Unit) =
26+
suspend inline fun mainTestScreen(block: suspend MainTestScreen.() -> Unit) =
2727
MainTestScreen(composeUiTest).block()
2828

29-
suspend fun noteScreen(block: suspend NoteScreen.() -> Unit) =
29+
suspend inline fun noteScreen(block: suspend NoteScreen.() -> Unit) =
3030
NoteScreen(composeUiTest).block()
3131

32-
suspend fun settingsTestScreen(block: suspend SettingsTestScreen.() -> Unit) =
32+
suspend inline fun settingsTestScreen(block: suspend SettingsTestScreen.() -> Unit) =
3333
SettingsTestScreen(composeUiTest).block()
3434

35-
suspend fun commonDialog(block: suspend CommonDialog.() -> Unit) =
35+
suspend inline fun commonDialog(block: suspend CommonDialog.() -> Unit) =
3636
commonDialog.block()
3737

38-
suspend fun editTitleDialog(block: suspend EditTitleDialog.() -> Unit) =
38+
suspend inline fun editTitleDialog(block: suspend EditTitleDialog.() -> Unit) =
3939
EditTitleDialog(commonDialog).block()
4040

41-
suspend fun confirmPasswordDialog(block: suspend ConfirmPasswordDialog.() -> Unit) =
41+
suspend inline fun confirmPasswordDialog(block: suspend ConfirmPasswordDialog.() -> Unit) =
4242
ConfirmPasswordDialog(commonDialog).block()
4343

44-
suspend fun enterPasswordDialog(block: suspend EnterPasswordDialog.() -> Unit) =
44+
suspend inline fun enterPasswordDialog(block: suspend EnterPasswordDialog.() -> Unit) =
4545
EnterPasswordDialog(commonDialog).block()
4646

47-
suspend fun changePasswordDialog(block: suspend ChangePasswordDialog.() -> Unit) =
47+
suspend inline fun changePasswordDialog(block: suspend ChangePasswordDialog.() -> Unit) =
4848
ChangePasswordDialog(commonDialog).block()
4949

50-
suspend fun languageDialog(block: suspend LanguageDialog.() -> Unit) =
50+
suspend inline fun languageDialog(block: suspend LanguageDialog.() -> Unit) =
5151
LanguageDialog(commonDialog).block()
5252
}

ui/test/src/commonMain/kotlin/com/softartdev/notedelight/ui/cases/CreateNoteWhileSelectedTestCase.kt

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ package com.softartdev.notedelight.ui.cases
55
import androidx.compose.ui.test.ComposeUiTest
66
import androidx.compose.ui.test.ExperimentalTestApi
77
import androidx.compose.ui.test.assertTextContains
8-
import androidx.compose.ui.test.assertIsDisplayed
98
import androidx.compose.ui.test.onNodeWithTag
109
import androidx.compose.ui.test.onNodeWithText
1110
import androidx.compose.ui.test.performClick
1211
import androidx.compose.ui.test.performTextInput
1312
import com.softartdev.notedelight.ui.BaseTestCase
14-
import com.softartdev.notedelight.ui.main.NOTE_TEXT_FIELD_TAG
13+
import com.softartdev.notedelight.ui.screen.MainTestScreen
1514
import com.softartdev.notedelight.util.CREATE_NOTE_FAB_TAG
1615
import com.softartdev.notedelight.waitAssert
1716
import com.softartdev.notedelight.waitUntilDisplayed
@@ -29,7 +28,6 @@ class CreateNoteWhileSelectedTestCase(
2928

3029
override fun invoke() = runTest {
3130
val noteText = Uuid.random().toString().substring(0, 30)
32-
3331
mainTestScreen {
3432
composeUiTest.waitUntilDisplayed("fab", blockSNI = ::fabSNI)
3533
fabSNI.performClick()
@@ -40,22 +38,24 @@ class CreateNoteWhileSelectedTestCase(
4038
composeUiTest.waitAssert("note text input applied") {
4139
textFieldSNI.assertTextContains(noteText)
4240
}
41+
saveNoteMenuButtonSNI.performClick()
42+
}
43+
MainTestScreen.noteItemTitleText = noteText
44+
mainTestScreen {
45+
val fabVisible = runCatching(this@mainTestScreen::fabSNI).isSuccess // `assertIsDisplayed` invokes in getter
46+
if (!fabVisible) return@runTest
47+
composeUiTest.waitUntilDisplayed("noteListItem", blockSNI = ::noteListItemSNI)
48+
noteListItemSNI.performClick()
4349
}
44-
45-
val fabVisible = runCatching {
46-
composeUiTest.onNodeWithTag(CREATE_NOTE_FAB_TAG).assertIsDisplayed()
47-
}.isSuccess
48-
if (!fabVisible) return@runTest
49-
5050
composeUiTest.onNodeWithTag(CREATE_NOTE_FAB_TAG).performClick()
51-
5251
commonDialog {
5352
composeUiTest.waitUntilDisplayed("saveChangesDialogYes", blockSNI = ::confirmDialogButtonSNI)
5453
}
5554
composeUiTest.onNodeWithText(getString(Res.string.cancel)).performClick()
56-
57-
composeUiTest.waitAssert("note text preserved") {
58-
composeUiTest.onNodeWithTag(NOTE_TEXT_FIELD_TAG).assertTextContains(noteText)
55+
noteScreen {
56+
composeUiTest.waitAssert("note text preserved") {
57+
textFieldSNI.assertTextContains(noteText)
58+
}
5959
}
6060
}
6161
}

0 commit comments

Comments
 (0)