diff --git a/.idea/misc.xml b/.idea/misc.xml index 8978d23..773fe0f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 68d4e47..fc2bd08 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -147,4 +147,4 @@ protobuf { } } } -} +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/FabTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/FabTest.kt new file mode 100644 index 0000000..fbd6968 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/FabTest.kt @@ -0,0 +1,74 @@ +package be.ugent.sel.studeez + +import androidx.compose.material.FloatingActionButton +import androidx.compose.ui.test.hasClickAction +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.common.composable.AddButtonActions +import be.ugent.sel.studeez.common.composable.ExpandedAddButton +import org.junit.Rule +import org.junit.Test + +class FabTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun expandFabTest() { + var expand = false + + composeTestRule.setContent { + FloatingActionButton( + onClick = {expand = true} + ) {} + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNode(hasClickAction()) + .assertExists() + .performClick() + + assert(expand) + } + + @Test + fun fabTest() { + var task = false + var session = false + var friend = false + + composeTestRule.setContent { + ExpandedAddButton( + addButtonActions = AddButtonActions( + {task = true}, + {friend = true}, + {session = true} + ) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithContentDescription("Session") + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription("Task") + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription("Friend") + .assertExists() + .performClick() + + assert(task) + assert(session) + assert(friend) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/HomeScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/HomeScreenTest.kt new file mode 100644 index 0000000..6906683 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/HomeScreenTest.kt @@ -0,0 +1,207 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onAllNodesWithContentDescription +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.common.composable.drawer.DrawerActions +import be.ugent.sel.studeez.common.composable.feed.FeedUiState +import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions +import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.screens.home.HomeScreen +import org.junit.Assert +import org.junit.Rule +import org.junit.Test + +class HomeScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun homeScreenTest() { + var continueTask = false + + composeTestRule.setContent { + HomeScreen( + drawerActions = DrawerActions({}, {}, {}, {}, {}), + navigationBarActions = NavigationBarActions({false}, {}, {}, {}, {}, {}, {}, {}), + feedUiState = FeedUiState.Succes(mapOf( + "08 May 2023" to listOf( + FeedEntry( + argb_color = 0xFFABD200, + subJectName = "Test Subject", + taskName = "Test Task", + totalStudyTime = 600, + ) + ) + )), + continueTask = {_, _ -> continueTask = true }, + onEmptyFeedHelp = {}, + onViewFriendsClick = {}, + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + "continue", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + Assert.assertTrue(continueTask) + } + + @Test + fun drawerTest() { + var homebuttontest = false + var timersbuttontest = false + var settingsbuttontest = false + var logoutbuttontest = false + var aboutbuttontest = false + + composeTestRule.setContent { + HomeScreen( + drawerActions = DrawerActions( + {homebuttontest = true}, + {timersbuttontest = true}, + {settingsbuttontest = true}, + {logoutbuttontest = true}, + {aboutbuttontest = true} + ), + navigationBarActions = NavigationBarActions({false}, {}, {}, {}, {}, {}, {}, {}), + feedUiState = FeedUiState.Succes(mapOf()), + continueTask = {_, _ -> }, + onEmptyFeedHelp = {}, + onViewFriendsClick = {}, + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onAllNodesWithText( + "home", + substring = true, + ignoreCase = true + )[2] // Third node has the button + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + "timer", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + "settings", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + "log out", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + "about", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + Assert.assertTrue(homebuttontest) + Assert.assertTrue(timersbuttontest) + Assert.assertTrue(settingsbuttontest) + Assert.assertTrue(logoutbuttontest) + Assert.assertTrue(aboutbuttontest) + } + + @Test + fun navigationbarTest() { + var hometest = false + var tasktest = false + var sessiontest = false + var profiletest = false + + composeTestRule.setContent { + HomeScreen( + drawerActions = DrawerActions({}, {}, {}, {}, {}), + navigationBarActions = NavigationBarActions( + {false}, + {hometest = true}, + {tasktest = true}, + {sessiontest = true}, + {profiletest = true}, + {}, {}, {} + ), + feedUiState = FeedUiState.Succes(mapOf()), + continueTask = {_, _ -> }, + onEmptyFeedHelp = {}, + onViewFriendsClick = {}, + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onAllNodesWithContentDescription( + "Home", + substring = true, + ignoreCase = true + )[0] // Third node has the button + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription( + "tasks", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription( + "session", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription( + "profile", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + Assert.assertTrue(hometest) + Assert.assertTrue(tasktest) + Assert.assertTrue(sessiontest) + Assert.assertTrue(profiletest) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/ExampleInstrumentedTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/InstrumentedTest.kt similarity index 95% rename from app/src/androidTest/java/be/ugent/sel/studeez/ExampleInstrumentedTest.kt rename to app/src/androidTest/java/be/ugent/sel/studeez/InstrumentedTest.kt index 06f9435..d6a1522 100644 --- a/app/src/androidTest/java/be/ugent/sel/studeez/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/be/ugent/sel/studeez/InstrumentedTest.kt @@ -14,7 +14,7 @@ import org.junit.Assert.* * See [testing documentation](http://d.android.com/tools/testing). */ @RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { +class InstrumentedTest { @Test fun useAppContext() { // Context of the app under test. diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/LoginScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/LoginScreenTest.kt new file mode 100644 index 0000000..9498241 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/LoginScreenTest.kt @@ -0,0 +1,68 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.screens.log_in.LoginScreen +import be.ugent.sel.studeez.screens.log_in.LoginScreenActions +import be.ugent.sel.studeez.screens.log_in.LoginUiState +import org.junit.Rule +import org.junit.Test + +class LoginScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun loginScreenTest() { + var login = false + var signup = false + var forgot_password = false + + composeTestRule.setContent { + LoginScreen( + uiState = LoginUiState(), + loginScreenActions = LoginScreenActions( + {}, {}, + {signup = true}, + {login = true}, + {forgot_password = true} + ) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onAllNodesWithText( + text = "Sign in", + substring = true, + ignoreCase = true + )[0] // The first object is the button + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "Forgot", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "Sign up", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(signup) + assert(login) + assert(forgot_password) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/ProfileEditScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/ProfileEditScreenTest.kt new file mode 100644 index 0000000..43c8240 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/ProfileEditScreenTest.kt @@ -0,0 +1,70 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.assert +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.screens.profile.edit_profile.EditProfileActions +import be.ugent.sel.studeez.screens.profile.edit_profile.EditProfileScreen +import be.ugent.sel.studeez.screens.profile.edit_profile.ProfileEditUiState +import org.junit.Rule +import org.junit.Test + +class ProfileEditScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun profileEditScreenTest() { + var edit_save = false + var goback = false + var delete_click = false + + composeTestRule.setContent { + EditProfileScreen( + goBack = {goback = true}, + uiState = ProfileEditUiState(), + editProfileActions = EditProfileActions( + onUserNameChange = {}, + onBiographyChange = {}, + onSaveClick = {edit_save = true}, + onDeleteClick = { delete_click = true }, + ), + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "save", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "delete", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription( + label = "go back", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(edit_save) + assert(goback) + assert(delete_click) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/ProfileScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/ProfileScreenTest.kt new file mode 100644 index 0000000..14e077d --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/ProfileScreenTest.kt @@ -0,0 +1,61 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.common.composable.drawer.DrawerActions +import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions +import be.ugent.sel.studeez.screens.profile.ProfileActions +import be.ugent.sel.studeez.screens.profile.ProfileScreen +import kotlinx.coroutines.flow.flowOf +import org.junit.Rule +import org.junit.Test + +class ProfileScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun profileScreenTest() { + var edit = false + var view_friends = false + + composeTestRule.setContent { + ProfileScreen( + profileActions = ProfileActions( + getUsername = {null}, + onEditProfileClick = {edit = true}, + getBiography = {null}, + getAmountOfFriends = { flowOf(0) }, + onViewFriendsClick = {view_friends = true} + ), + drawerActions = DrawerActions({}, {}, {}, {}, {}), + navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithContentDescription( + label = "edit profile", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "friends", + substring = true, + ignoreCase = true, + ) + .assertExists() + .performClick() + + assert(edit) + assert(view_friends) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/SessionRecapScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/SessionRecapScreenTest.kt new file mode 100644 index 0000000..829152b --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/SessionRecapScreenTest.kt @@ -0,0 +1,75 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.data.local.models.SessionReport +import be.ugent.sel.studeez.screens.session_recap.SessionRecapActions +import be.ugent.sel.studeez.screens.session_recap.SessionRecapScreen +import com.google.firebase.Timestamp +import org.junit.Assert +import org.junit.Rule +import org.junit.Test + + +class SessionRecapScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun sessionRecapTest() { + var saveCalled = false + var discardCalled = false + + composeTestRule.setContent { + SessionRecapScreen( + Modifier, + SessionRecapActions( + { + SessionReport( + "", + 0, + Timestamp(0, 0), + "") + }, + { saveCalled = true }, + { discardCalled = true } + ) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + "You studied", + substring = true, + ignoreCase = true + ) + .assertExists() + + composeTestRule + .onNodeWithText( + "save", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + "discard", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + Assert.assertTrue(saveCalled) + Assert.assertTrue(discardCalled) + } + + +} diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/SignUpScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/SignUpScreenTest.kt new file mode 100644 index 0000000..c7b5f41 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/SignUpScreenTest.kt @@ -0,0 +1,52 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.screens.sign_up.SignUpActions +import be.ugent.sel.studeez.screens.sign_up.SignUpScreen +import be.ugent.sel.studeez.screens.sign_up.SignUpUiState +import org.junit.Rule +import org.junit.Test + +class SignUpScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun signupScreenTest() { + var create = false + var login = false + + composeTestRule.setContent { + SignUpScreen( + uiState = SignUpUiState(), + signUpActions = SignUpActions({}, {}, {}, {}, {create = true}, {login = true}) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "log in", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onAllNodesWithText( + text = "Create account", + substring = true, + ignoreCase = true + )[0] // First node has the button + .assertExists() + .performClick() + + assert(login) + assert(create) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/SplashScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/SplashScreenTest.kt new file mode 100644 index 0000000..6a43119 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/SplashScreenTest.kt @@ -0,0 +1,40 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.screens.splash.SplashScreen +import org.junit.Rule +import org.junit.Test + +class SplashScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun splashScreenTest() { + var tryAgain = false + + composeTestRule.setContent { + SplashScreen( + Modifier, + {tryAgain = true}, + true + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onAllNodesWithText( + text = "try again", + substring = true, + ignoreCase = true + )[1] // Second node is the button + .assertExists() + .performClick() + + assert(tryAgain) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/SubjectScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/SubjectScreenTest.kt new file mode 100644 index 0000000..d4b5c68 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/SubjectScreenTest.kt @@ -0,0 +1,158 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.common.composable.DeleteButton +import be.ugent.sel.studeez.common.composable.drawer.DrawerActions +import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions +import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.screens.subjects.SubjectScreen +import be.ugent.sel.studeez.screens.subjects.SubjectUiState +import be.ugent.sel.studeez.screens.subjects.form.SubjectForm +import be.ugent.sel.studeez.screens.subjects.form.SubjectFormUiState +import kotlinx.coroutines.flow.flowOf +import org.junit.Rule +import org.junit.Test + +class SubjectScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun addSubjectScreenTest() { + var confirm = false + var goback = false + + composeTestRule.setContent { + SubjectForm( + title = R.string.new_subject, + goBack = {goback = true}, + uiState = SubjectFormUiState(), + onConfirm = {confirm = true}, + onNameChange = {}, + onColorChange = {}, + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "confirm", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription( + label = "go back", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(confirm) + assert(goback) + } + + @Test + fun editSubjectScreenTest() { + var confirm = false + var delete = false + + composeTestRule.setContent { + SubjectForm( + title = R.string.edit_subject, + goBack = {}, + uiState = SubjectFormUiState( + name = "Test Subject", + ), + onConfirm = {confirm = true}, + onNameChange = {}, + onColorChange = {}, + ) + DeleteButton(text = R.string.delete_subject) { + delete = true + } + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "confirm", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "delete", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(confirm) + assert(delete) + } + + @Test + fun subjectScreenTest() { + var view = false + var add = false + + composeTestRule.setContent { + SubjectScreen( + drawerActions = DrawerActions({}, {}, {}, {}, {}), + navigationBarActions = NavigationBarActions({false}, {}, {}, {}, {}, {}, {}, {}), + onAddSubject = { add = true }, + onViewSubject = { view = true }, + getStudyTime = { flowOf() }, + getCompletedTaskCount = { flowOf() }, + getTaskCount = { flowOf() }, + uiState = SubjectUiState.Succes( + listOf( + Subject( + id = "", + name = "Test Subject", + argb_color = 0xFFFFD200, + archived = false + ) + ) + ) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "view", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "new subject", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(add) + assert(view) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/TaskScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/TaskScreenTest.kt new file mode 100644 index 0000000..0f7a8b8 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/TaskScreenTest.kt @@ -0,0 +1,160 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.common.composable.DeleteButton +import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.data.local.models.task.Task +import be.ugent.sel.studeez.screens.tasks.TaskActions +import be.ugent.sel.studeez.screens.tasks.TaskScreen +import be.ugent.sel.studeez.screens.tasks.form.TaskForm +import be.ugent.sel.studeez.screens.tasks.form.TaskFormUiState +import kotlinx.coroutines.flow.flowOf +import org.junit.Rule +import org.junit.Test + +class TaskScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun addTaskScreenTest() { + var confirm = false + var goback = false + + composeTestRule.setContent { + TaskForm( + title = R.string.new_task, + goBack = {goback = true}, + uiState = TaskFormUiState(), + onConfirm = {confirm = true}, + onNameChange = {}, + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "confirm", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithContentDescription( + label = "go back", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(confirm) + assert(goback) + } + + @Test + fun editTaskScreenTest() { + var confirm = false + var delete = false + + composeTestRule.setContent { + TaskForm( + title = R.string.edit_task, + goBack = {}, + uiState = TaskFormUiState( + name = "Test Task", + ), + onConfirm = {confirm = true}, + onNameChange = {}, + ) { + DeleteButton(text = R.string.delete_task) { + delete = true + } + } + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "confirm", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "delete", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(confirm) + assert(delete) + } + + @Test + fun taskScreenTest() { + var add = false + var edit = false + var start = false + + composeTestRule.setContent { + TaskScreen( + goBack = {}, + taskActions = TaskActions( + {add = true}, + { Subject(name = "Test Subject") }, + { flowOf(listOf(Task())) }, + { _, _ -> run {} }, + {edit = true}, + {start = true}, + {}, + ) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithContentDescription( + label = "edit", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "new", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "start", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(add) + assert(edit) + assert(start) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/TimerOverviewScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/TimerOverviewScreenTest.kt new file mode 100644 index 0000000..357bed4 --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/TimerOverviewScreenTest.kt @@ -0,0 +1,58 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.common.composable.drawer.DrawerActions +import be.ugent.sel.studeez.data.local.models.timer_info.EndlessTimerInfo +import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewActions +import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewScreen +import kotlinx.coroutines.flow.flowOf +import org.junit.Rule +import org.junit.Test + +class TimerOverviewScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun timerOverviewScreenTest() { + var add = false + var edit = false + + composeTestRule.setContent { + TimerOverviewScreen( + timerOverviewActions = TimerOverviewActions( + { flowOf(listOf(EndlessTimerInfo("", ""))) }, + { listOf() }, + {edit = true}, + {add = true} + ), + drawerActions = DrawerActions({}, {}, {}, {}, {}) + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "add", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + composeTestRule + .onNodeWithText( + text = "edit", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(add) + assert(edit) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/be/ugent/sel/studeez/TimerSelectionScreenTest.kt b/app/src/androidTest/java/be/ugent/sel/studeez/TimerSelectionScreenTest.kt new file mode 100644 index 0000000..f055daa --- /dev/null +++ b/app/src/androidTest/java/be/ugent/sel/studeez/TimerSelectionScreenTest.kt @@ -0,0 +1,40 @@ +package be.ugent.sel.studeez + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionActions +import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionScreen +import kotlinx.coroutines.flow.flowOf +import org.junit.Rule +import org.junit.Test + +class TimerSelectionScreenTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun timerOverviewScreenTest() { + var start = false + + composeTestRule.setContent { + TimerSelectionScreen( + timerSelectionActions = TimerSelectionActions({ flowOf()}, {start = true}, 0), + popUp = {} + ) + } + + composeTestRule.waitForIdle() + + composeTestRule + .onNodeWithText( + text = "start", + substring = true, + ignoreCase = true + ) + .assertExists() + .performClick() + + assert(start) + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt index 261f3e0..88c48c0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt @@ -1,7 +1,6 @@ package be.ugent.sel.studeez.data.local.models.task import com.google.firebase.firestore.DocumentId -import com.google.firebase.firestore.Exclude data class Subject( @DocumentId val id: String = "", diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseSubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseSubjectDAO.kt index f1571d7..05e0258 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseSubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseSubjectDAO.kt @@ -91,4 +91,4 @@ class FirebaseSubjectDAO @Inject constructor( fun Query.subjectNotArchived(): Query = this.whereEqualTo(SubjectDocument.archived, false) -} \ No newline at end of file +} diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/InvisibleSessionManager.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/InvisibleSessionManager.kt index 763fb1d..8a7c405 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/InvisibleSessionManager.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/InvisibleSessionManager.kt @@ -1,10 +1,6 @@ package be.ugent.sel.studeez.screens.session -import android.annotation.SuppressLint -import android.content.Context import android.media.MediaPlayer -import android.media.RingtoneManager -import android.net.Uri import kotlinx.coroutines.delay import javax.inject.Singleton import kotlin.time.Duration.Companion.seconds @@ -14,10 +10,8 @@ object InvisibleSessionManager { private var viewModel: SessionViewModel? = null private lateinit var mediaPlayer: MediaPlayer - fun setParameters(viewModel: SessionViewModel, context: Context) { - val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) - this.mediaPlayer = MediaPlayer.create(context, uri) - this.mediaPlayer.isLooping = false + fun setParameters(viewModel: SessionViewModel, mediaPlayer: MediaPlayer) { + this.mediaPlayer = mediaPlayer this.viewModel = viewModel } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionRoute.kt index aeaf544..6ca8a96 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionRoute.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionRoute.kt @@ -1,5 +1,8 @@ package be.ugent.sel.studeez.screens.session +import android.media.MediaPlayer +import android.media.RingtoneManager +import android.net.Uri import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer @@ -28,8 +31,11 @@ fun SessionRoute( openAndPopUp: (String, String) -> Unit, viewModel: SessionViewModel, ) { + val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) + val mediaPlayer = MediaPlayer.create(LocalContext.current, uri) + mediaPlayer.isLooping = false - InvisibleSessionManager.setParameters(viewModel = viewModel, context = LocalContext.current) + InvisibleSessionManager.setParameters(viewModel = viewModel, mediaPlayer = mediaPlayer) val soundPlayer = SoundPlayer(LocalContext.current) val sessionActions = getSessionActions(viewModel, openAndPopUp) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index 9e787dd..196ad3f 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -18,7 +18,6 @@ import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.DeleteButton import be.ugent.sel.studeez.common.composable.FormComposable import be.ugent.sel.studeez.common.composable.LabelledInputField -import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.common.ext.fieldModifier import be.ugent.sel.studeez.common.ext.generateRandomArgb diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt index 7a1554b..84162d0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt @@ -2,8 +2,6 @@ package be.ugent.sel.studeez.screens.subjects.form import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf -import androidx.compose.ui.graphics.Color -import be.ugent.sel.studeez.common.ext.generateRandomArgb import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.domain.LogService diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormScreen.kt index fea01e6..c69e929 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormScreen.kt @@ -4,7 +4,6 @@ import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import be.ugent.sel.studeez.common.composable.DeleteButton -import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate import be.ugent.sel.studeez.common.composable.FormComposable import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo import be.ugent.sel.studeez.R.string as AppText diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt index 4825c63..3663e4a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate @@ -46,4 +47,13 @@ fun TimerTypeSelectScreen( } } } +} + +@Preview +@Composable +fun TimerTypeSelectScreenPreview() { + TimerTypeSelectScreen( + open = {}, + popUp = {} + ) } \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt index 4b259c8..89a9b17 100644 --- a/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt @@ -7,13 +7,14 @@ import org.junit.Test class FunctionalPomodoroTimerUnitTest : FunctionalTimerUnitTest() { private val breakTime = 10 private val breaks = 2 + private val repeats = 3 // = breaks + 1 override val hours = 0 override val minutes = 0 override val seconds = 10 private lateinit var pomodoroTimer: FunctionalPomodoroTimer override fun setTimer() { - pomodoroTimer = FunctionalPomodoroTimer(time, breakTime, breaks) + pomodoroTimer = FunctionalPomodoroTimer(time, breakTime, repeats) } @Test diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt index 54f673d..891c379 100644 --- a/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt @@ -1,12 +1,11 @@ package be.ugent.sel.studeez.timer_functional -import android.media.MediaPlayer import be.ugent.sel.studeez.data.SelectedSessionReport +import be.ugent.sel.studeez.data.SelectedTask import be.ugent.sel.studeez.data.SelectedTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalCustomTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer -import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.implementation.LogServiceImpl import be.ugent.sel.studeez.screens.session.InvisibleSessionManager import be.ugent.sel.studeez.screens.session.SessionViewModel @@ -22,13 +21,13 @@ import org.mockito.kotlin.mock class InvisibleSessionManagerTest { private var selectedTimer: SelectedTimer = SelectedTimer() private lateinit var viewModel: SessionViewModel - private var mediaPlayer: MediaPlayer = mock() + @Test fun InvisibleEndlessTimerTest() = runTest { selectedTimer.set(FunctionalEndlessTimer()) - viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) - InvisibleSessionManager.setParameters(viewModel, mediaPlayer) + viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), SelectedTask(), LogServiceImpl()) + InvisibleSessionManager.setParameters(viewModel, mock()) val test = launch { InvisibleSessionManager.updateTimer() @@ -47,10 +46,10 @@ class InvisibleSessionManagerTest { fun InvisiblePomodoroTimerTest() = runTest { val studyTime = 10 val breakTime = 5 - val repeats = 1 + val repeats = 2 selectedTimer.set(FunctionalPomodoroTimer(studyTime, breakTime, repeats)) - viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) - InvisibleSessionManager.setParameters(viewModel, mediaPlayer) + viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), SelectedTask(), LogServiceImpl()) + InvisibleSessionManager.setParameters(viewModel, mock()) val test = launch { InvisibleSessionManager.updateTimer() @@ -82,8 +81,8 @@ class InvisibleSessionManagerTest { @Test fun InvisibleCustomTimerTest() = runTest { selectedTimer.set(FunctionalCustomTimer(5)) - viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) - InvisibleSessionManager.setParameters(viewModel, mediaPlayer) + viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), SelectedTask(), LogServiceImpl()) + InvisibleSessionManager.setParameters(viewModel, mock()) val test = launch { InvisibleSessionManager.updateTimer() diff --git a/build.gradle b/build.gradle index 7f25617..4535dd7 100644 --- a/build.gradle +++ b/build.gradle @@ -21,4 +21,3 @@ plugins { // Hilt id 'com.google.dagger.hilt.android' version '2.44' apply false } - diff --git a/gradle.properties b/gradle.properties index edf11ef..8581bd2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,4 +22,6 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +android.defaults.buildfeatures.buildconfig=true +android.nonFinalResIds=false \ No newline at end of file