Skip to content

Commit

Permalink
Merge branch 'develop' into ANDROAPP-4826-Display-message-when-event-…
Browse files Browse the repository at this point in the history
…has-no-sections-or-data-elements-config-issue
  • Loading branch information
DavidAparicioAlbaAsenjo authored Feb 20, 2024
2 parents e29cc3e + 80b307d commit 5a9588b
Show file tree
Hide file tree
Showing 25 changed files with 980 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import org.dhis2.usescases.datasets.DataSetTest
import org.dhis2.usescases.enrollment.EnrollmentTest
import org.dhis2.usescases.event.EventTest
import org.dhis2.usescases.filters.FilterTest
import org.dhis2.usescases.form.FormTest
import org.dhis2.usescases.jira.JiraTest
import org.dhis2.usescases.login.LoginTest
import org.dhis2.usescases.main.MainTest
Expand All @@ -15,6 +14,7 @@ import org.dhis2.usescases.searchte.SearchTETest
import org.dhis2.usescases.settings.SettingsTest
import org.dhis2.usescases.sync.SyncActivityTest
import org.dhis2.usescases.teidashboard.TeiDashboardTest
import org.dhis2.usescases.teidashboard.dialogs.scheduling.SchedulingDialogUiTest
import org.junit.runner.RunWith
import org.junit.runners.Suite

Expand All @@ -33,6 +33,7 @@ import org.junit.runners.Suite
SearchTETest::class,
SettingsTest::class,
SyncActivityTest::class,
TeiDashboardTest::class
TeiDashboardTest::class,
SchedulingDialogUiTest::class,
)
class UseCaseTestsSuite
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package org.dhis2.usescases.teidashboard.dialogs.scheduling

import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import kotlinx.coroutines.flow.MutableStateFlow
import org.dhis2.composetable.test.TestActivity
import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.models.EventCatCombo
import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.models.EventCategory
import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.models.EventDate
import org.dhis2.usescases.teiDashboard.dialogs.scheduling.SchedulingDialogUi
import org.dhis2.usescases.teiDashboard.dialogs.scheduling.SchedulingViewModel
import org.hisp.dhis.android.core.category.CategoryOption
import org.hisp.dhis.android.core.program.ProgramStage
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

class SchedulingDialogUiTest {

@get:Rule
val composeTestRule = createAndroidComposeRule<TestActivity>()

private val viewModel: SchedulingViewModel = mock()

@Before
fun setUp() {
whenever(viewModel.eventDate).thenReturn(MutableStateFlow(EventDate(label = "Date")))
whenever(viewModel.eventCatCombo).thenReturn(
MutableStateFlow(
EventCatCombo(
categories = listOf(
EventCategory(
uid = "uid",
name = "CatCombo",
optionsSize = 2,
options = listOf(
CategoryOption.builder().uid("uidA").displayName("optionA").build(),
CategoryOption.builder().uid("uidB").displayName("optionB").build(),
),
),
),
),
),
)
}

@Test
fun programStageInputNotDisplayedForOneStage() {
val programStages = listOf(ProgramStage.builder().uid("stageUid").displayName("PS A").build())
whenever(viewModel.programStage).thenReturn(MutableStateFlow(programStages.first()))
composeTestRule.setContent {
SchedulingDialogUi(
programStages = programStages,
viewModel = viewModel,
orgUnitUid = "orgUnitUid",
) {
}
}
composeTestRule.onNodeWithText("Schedule next " + programStages.first().displayName() + "?").assertExists()
composeTestRule.onNodeWithText("Program stage").assertDoesNotExist()
composeTestRule.onNodeWithText("Date").assertExists()
composeTestRule.onNodeWithText("CatCombo *").assertExists()
composeTestRule.onNodeWithText("Schedule").assertExists()
}

@Test
fun programStageInputDisplayedForMoreThanOneStages() {
val programStages = listOf(
ProgramStage.builder().uid("stageUidA").displayName("PS A").build(),
ProgramStage.builder().uid("stageUidB").displayName("PS B").build(),
)
whenever(viewModel.programStage).thenReturn(MutableStateFlow(programStages.first()))
composeTestRule.setContent {
SchedulingDialogUi(
programStages = programStages,
viewModel = viewModel,
orgUnitUid = "orgUnitUid",
) {
}
}
composeTestRule.onNodeWithText("Schedule next event?").assertExists()
composeTestRule.onNodeWithText("Program stage").assertExists()
}

@Test
fun inputFieldsShouldNotBeDisplayedWhenAnsweringNo() {
val programStages = listOf(
ProgramStage.builder().uid("stageUidA").displayName("PS A").build(),
ProgramStage.builder().uid("stageUidB").displayName("PS B").build(),
)
whenever(viewModel.programStage).thenReturn(MutableStateFlow(programStages.first()))
composeTestRule.setContent {
SchedulingDialogUi(
programStages = programStages,
viewModel = viewModel,
orgUnitUid = "orgUnitUid",
) {
}
}
composeTestRule.onNodeWithText("No").performClick()

composeTestRule.onNodeWithText("Program stage").assertDoesNotExist()
composeTestRule.onNodeWithText("Date").assertDoesNotExist()
composeTestRule.onNodeWithText("CatCombo *").assertDoesNotExist()
composeTestRule.onNodeWithText("Done").assertExists()
}

@Test
fun selectProgramStage() {
val programStages = listOf(
ProgramStage.builder().uid("stageUidA").displayName("PS A").build(),
ProgramStage.builder().uid("stageUidB").displayName("PS B").build(),
)
whenever(viewModel.programStage).thenReturn(MutableStateFlow(programStages.first()))
composeTestRule.setContent {
SchedulingDialogUi(
programStages = programStages,
viewModel = viewModel,
orgUnitUid = "orgUnitUid",
) {
}
}

composeTestRule.onNodeWithText("Program stage").performClick()
composeTestRule.onNodeWithTag("INPUT_DROPDOWN_MENU_ITEM_1").performClick()

verify(viewModel).updateStage(programStages[1])
}
}
5 changes: 5 additions & 0 deletions app/src/main/java/org/dhis2/data/user/UserComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
import org.dhis2.usescases.teiDashboard.TeiDashboardModule;
import org.dhis2.usescases.teiDashboard.dashboardfragments.relationships.RelationshipComponent;
import org.dhis2.usescases.teiDashboard.dashboardfragments.relationships.RelationshipModule;
import org.dhis2.usescases.teiDashboard.dialogs.scheduling.SchedulingComponent;
import org.dhis2.usescases.teiDashboard.dialogs.scheduling.SchedulingModule;
import org.dhis2.usescases.teiDashboard.teiProgramList.TeiProgramListComponent;
import org.dhis2.usescases.teiDashboard.teiProgramList.TeiProgramListModule;
import org.dhis2.utils.optionset.OptionSetComponent;
Expand Down Expand Up @@ -204,4 +206,7 @@ public interface UserComponent {

@NonNull
SessionComponent plus(PinModule pinModule);

@NonNull
SchedulingComponent plus(SchedulingModule schedulingModule);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.dhis2.usescases.eventsWithoutRegistration.eventDetails.data

import io.reactivex.Observable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import org.dhis2.data.dhislogic.AUTH_ALL
import org.dhis2.data.dhislogic.AUTH_UNCOMPLETE_EVENT
import org.dhis2.form.model.FieldUiModel
Expand All @@ -17,21 +19,23 @@ import org.hisp.dhis.android.core.common.ObjectStyle
import org.hisp.dhis.android.core.common.ValueType
import org.hisp.dhis.android.core.enrollment.EnrollmentStatus
import org.hisp.dhis.android.core.event.Event
import org.hisp.dhis.android.core.event.EventCreateProjection
import org.hisp.dhis.android.core.event.EventEditableStatus
import org.hisp.dhis.android.core.event.EventObjectRepository
import org.hisp.dhis.android.core.event.EventStatus
import org.hisp.dhis.android.core.maintenance.D2Error
import org.hisp.dhis.android.core.organisationunit.OrganisationUnit
import org.hisp.dhis.android.core.program.Program
import org.hisp.dhis.android.core.program.ProgramStage
import java.util.Calendar
import java.util.Date

class EventDetailsRepository(
private val d2: D2,
private val programUid: String,
private val eventUid: String?,
private val programStageUid: String?,
private val fieldFactory: FieldViewModelFactory,
private val fieldFactory: FieldViewModelFactory?,
private val onError: (Throwable) -> String?,
) {

Expand Down Expand Up @@ -173,7 +177,7 @@ class EventDetailsRepository(
d2.eventModule().events().uid(eventUid).blockingGet()?.geometry()?.coordinates()
}

return fieldFactory.create(
return fieldFactory!!.create(
id = "",
label = "",
valueType = ValueType.COORDINATE,
Expand Down Expand Up @@ -325,4 +329,33 @@ class EventDetailsRepository(
),
)
}

fun scheduleEvent(
enrollmentUid: String?,
dueDate: Date,
orgUnitUid: String?,
categoryOptionComboUid: String?,
): Flow<String?> = flow {
val cal = Calendar.getInstance()
cal.time = dueDate
cal[Calendar.HOUR_OF_DAY] = 0
cal[Calendar.MINUTE] = 0
cal[Calendar.SECOND] = 0
cal[Calendar.MILLISECOND] = 0

val uid = d2.eventModule().events().blockingAdd(
EventCreateProjection.builder()
.enrollment(enrollmentUid)
.program(programUid)
.programStage(programStageUid)
.organisationUnit(orgUnitUid)
.attributeOptionCombo(categoryOptionComboUid)
.build(),
)
val eventRepository = d2.eventModule().events().uid(uid)
eventRepository.setDueDate(cal.time)
eventRepository.setStatus(EventStatus.SCHEDULE)

emit(uid)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class ConfigureEventCatCombo(
repository.catCombo().apply {
val categories = getCategories(this?.categories())
val categoryOptions = getCategoryOptions()
updateSelectedOptions(categoryOption, categories, categoryOptions)
val catComboUid = getCatComboUid(this?.uid() ?: "", this?.isDefault ?: false)
val catComboDisplayName = getCatComboDisplayName(this?.uid() ?: "")
updateSelectedOptions(categoryOption, categories, categoryOptions)

return flowOf(
EventCatCombo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,13 @@ fun ProvideCategorySelector(
modifier: Modifier = Modifier,
eventCatComboUiModel: EventCatComboUiModel,
) {
var selectedItem by remember {
mutableStateOf(
eventCatComboUiModel.eventCatCombo.selectedCategoryOptions[eventCatComboUiModel.category.uid]?.displayName()
?: eventCatComboUiModel.eventCatCombo.categoryOptions?.get(eventCatComboUiModel.category.uid)?.displayName(),
)
var selectedItem by with(eventCatComboUiModel) {
remember(this) {
mutableStateOf(
eventCatCombo.selectedCategoryOptions[category.uid]?.displayName()
?: eventCatCombo.categoryOptions?.get(category.uid)?.displayName(),
)
}
}

val selectableOptions = eventCatComboUiModel.category.options
Expand Down
Loading

0 comments on commit 5a9588b

Please sign in to comment.