-
Notifications
You must be signed in to change notification settings - Fork 1
Fix #12, #16, #18: Add GitHub OAuth, error handling, and navigation #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
463e490
Add LoginButton composable and integrate it into MainActivity
theMr17 d084a29
Add CLIENT_ID and CLIENT_SECRET to buildConfig in debug and release b…
theMr17 ed82b5a
Add GitHub OAuth integration with LoginButton and createGitHubAuthIntent
theMr17 7058ed3
Add LoginScreen composable and update MainActivity to use it
theMr17 bbedd44
Add authentication feature with ViewModel, data sources, and error ha…
theMr17 1b7b3b5
Add ConnectingToGitHubScreen and navigation setup in MainActivity
theMr17 9c6c7ac
Update build.gradle.kts to handle missing local.properties gracefully…
theMr17 2cda0cc
Add GitHub connection handling with state management and navigation s…
theMr17 2bb8b02
Rename authentication-related classes and update references to improv…
theMr17 b710a5e
Update SetupStep enum documentation to clarify token retrieval proces…
theMr17 99577cd
Merge branch 'main' into feat/setup-authentication-flow
theMr17 6e396b2
Fix daggerHilt variable name
theMr17 bbb0150
Refactor error handling in DataStore operations and update related cl…
theMr17 0d604e8
Update test script to include verbose output for connectedAndroidTest
theMr17 de4f862
Enhance test script to handle emulator termination on test failure
theMr17 a34fa01
Revert changes to test.yml
theMr17 fb5a0cd
Refactor DataStoreManager tests to assert Result type and improve cla…
theMr17 a52d591
Add splash screen support and update app theme
theMr17 3e586c4
Refactor splash screen implementation and set post-splash theme
theMr17 d15d412
Inject HttpClientFactory into provideHttpClient and retrieve access t…
theMr17 3dae001
Enhance login flow with navigation events and update LoginButton to a…
theMr17 62fe4ed
Implement GitHub OAuth flow with state management and DataStore integ…
theMr17 bff5863
Refactor login flow to enhance state management and navigation events
theMr17 6afc242
Enhance setup flow with detailed documentation for events and actions
theMr17 70d8aa1
Use Truth assertions and move HttpClientFactoryTest to AndroidTest
theMr17 ef3ad69
Add Ktor client mock dependency for enhanced testing capabilities
theMr17 3d16713
Implement BaseViewModel to streamline state management and event hand…
theMr17 cd217c8
Add test tags to CircularProgressIndicator and implement LoginScreen …
theMr17 eaf8dc1
Refactor test tag for CircularProgressIndicator in LoginScreen for co…
theMr17 85b58b6
Add unit tests for SetupScreen to verify UI states and interactions
theMr17 204c1c2
Add string resources for login and setup screen messages
theMr17 2421855
Refactor state management in ViewModels and enhance LoginScreen tests…
theMr17 ab617e5
Update text assertions in LoginScreen and SetupScreen tests to use el…
theMr17 fb731c8
Add LoginViewModel tests for authentication status and navigation events
theMr17 ffa69e8
Refactor LoginViewModelTest to initialize ViewModel only once in setup
theMr17 9ad2666
Rename test methods in LoginViewModelTest for clarity and consistency
theMr17 40adaa8
Add SetupViewModel tests for initial state and auth token handling
theMr17 132ef54
Refactor SetupViewModelTest to remove unnecessary map calls and impro…
theMr17 18192d4
Enhance BaseViewModel with detailed documentation and improve error h…
theMr17 478a1f3
Refactor SetupViewModelTest to improve test clarity and structure wit…
theMr17 9d01787
Refactor SetupViewModelTest to use mock methods for OAuth state handling
theMr17 e86b940
Refactor LoginViewModel to remove logging on auth error and simplify …
theMr17 26547ec
Revert "Refactor LoginViewModel to remove logging on auth error and s…
theMr17 ba8c99d
Add tests for getAuthToken in SetupViewModel to verify state transiti…
theMr17 3ecbbf6
Fix formatting in mockSetAccessTokenError function in SetupViewModelTest
theMr17 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
app/src/androidTest/java/com/notifier/app/auth/presentation/login/LoginScreenTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| package com.notifier.app.auth.presentation.login | ||
|
|
||
| import androidx.compose.ui.test.assertIsDisplayed | ||
| import androidx.compose.ui.test.hasTestTag | ||
| import androidx.compose.ui.test.junit4.createComposeRule | ||
| import androidx.compose.ui.test.onNodeWithText | ||
| import androidx.compose.ui.test.performClick | ||
| import com.google.common.truth.Truth.assertThat | ||
| import org.junit.Rule | ||
| import org.junit.Test | ||
|
|
||
|
theMr17 marked this conversation as resolved.
|
||
| class LoginScreenTest { | ||
| @get:Rule | ||
| val composeRule = createComposeRule() | ||
|
|
||
| @Test | ||
| fun testLoginScreen_whenStatusIsNull_showsProgressAndMessage() { | ||
| composeRule.setContent { | ||
| LoginScreen( | ||
| state = LoginState(status = null), | ||
| onLoginButtonClick = {} | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNode(hasTestTag(TEST_TAG_CIRCULAR_PROGRESS_INDICATOR)) | ||
| .assertExists() | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Verifying authentication status…") | ||
| .assertIsDisplayed() | ||
| } | ||
|
|
||
| @Test | ||
| fun testLoginScreen_whenLoading_showsProgressAndMessage() { | ||
| composeRule.setContent { | ||
| LoginScreen( | ||
| state = LoginState(status = LoginStatus.LOADING), | ||
| onLoginButtonClick = {} | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNode(hasTestTag(TEST_TAG_CIRCULAR_PROGRESS_INDICATOR)) | ||
| .assertExists() | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Verifying authentication status…") | ||
| .assertIsDisplayed() | ||
| } | ||
|
|
||
| @Test | ||
| fun testLoginScreen_whenLoggedOut_showsLoginButton_clickTriggersCallback() { | ||
| var loginButtonClicked = false | ||
|
|
||
| composeRule.setContent { | ||
| LoginScreen( | ||
| state = LoginState(status = LoginStatus.LOGGED_OUT), | ||
| onLoginButtonClick = { loginButtonClicked = true } | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Login with GitHub") | ||
| .assertIsDisplayed() | ||
| .performClick() | ||
|
|
||
| assertThat(loginButtonClicked).isTrue() | ||
| } | ||
|
|
||
| @Test | ||
| fun testLoginScreen_whenLoggedIn_showsSuccessMessage() { | ||
| composeRule.setContent { | ||
| LoginScreen( | ||
| state = LoginState(status = LoginStatus.LOGGED_IN), | ||
| onLoginButtonClick = {} | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Logged in successfully! Redirecting…") | ||
| .assertIsDisplayed() | ||
| } | ||
| } | ||
97 changes: 97 additions & 0 deletions
97
app/src/androidTest/java/com/notifier/app/auth/presentation/login/LoginViewModelTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| package com.notifier.app.auth.presentation.login | ||
|
|
||
| import com.google.common.truth.Truth.assertThat | ||
| import com.notifier.app.core.data.persistence.DataStoreManager | ||
| import com.notifier.app.core.domain.util.PersistenceError | ||
| import com.notifier.app.core.domain.util.Result | ||
| import io.mockk.coEvery | ||
| import io.mockk.mockk | ||
| import kotlinx.coroutines.flow.first | ||
| import kotlinx.coroutines.flow.map | ||
| import kotlinx.coroutines.flow.take | ||
| import kotlinx.coroutines.flow.toList | ||
| import kotlinx.coroutines.test.runTest | ||
| import org.junit.Before | ||
| import org.junit.Test | ||
|
|
||
| class LoginViewModelTest { | ||
| private lateinit var dataStoreManager: DataStoreManager | ||
|
|
||
| private lateinit var viewModel: LoginViewModel | ||
|
|
||
| @Before | ||
| fun setUp() { | ||
| dataStoreManager = mockk() | ||
| viewModel = LoginViewModel(dataStoreManager) | ||
| } | ||
|
|
||
| @Test | ||
| fun testAuthStatus_tokenIsValid_setsStateToLoggedInEventually() = runTest { | ||
| coEvery { | ||
| dataStoreManager.getAccessToken() | ||
| } returns Result.Success("dummy_valid_token") | ||
|
|
||
| val stateStatuses = viewModel.state | ||
| .take(3) | ||
| .map { it.status } | ||
| .toList() | ||
|
|
||
| assertThat(stateStatuses).containsExactly( | ||
| null, | ||
| LoginStatus.LOADING, | ||
| LoginStatus.LOGGED_IN | ||
| ).inOrder() | ||
| } | ||
|
|
||
| @Test | ||
| fun testAuthStatus_tokenIsBlank_setsStateToLoggedOutEventually() = runTest { | ||
| coEvery { | ||
| dataStoreManager.getAccessToken() | ||
| } returns Result.Success("") | ||
|
|
||
| val stateStatuses = viewModel.state | ||
| .take(3) | ||
| .map { it.status } | ||
| .toList() | ||
|
|
||
| assertThat(stateStatuses).containsExactly( | ||
| null, | ||
| LoginStatus.LOADING, | ||
| LoginStatus.LOGGED_OUT | ||
| ).inOrder() | ||
| } | ||
|
|
||
| @Test | ||
| fun testAuthStatus_errorFetchingToken_setsStateToLoggedOutEventually() = runTest { | ||
| coEvery { | ||
| dataStoreManager.getAccessToken() | ||
| } returns Result.Error(PersistenceError.IO) | ||
|
|
||
| val stateStatuses = viewModel.state | ||
| .take(3) | ||
| .map { it.status } | ||
| .toList() | ||
|
|
||
| assertThat(stateStatuses).containsExactly( | ||
| null, | ||
| LoginStatus.LOADING, | ||
| LoginStatus.LOGGED_OUT | ||
| ).inOrder() | ||
| } | ||
|
|
||
| @Test | ||
| fun testOnAction_onLoginButtonClick_emitsNavigateToGitHubAuthEvent() = runTest { | ||
| viewModel.onAction(LoginAction.OnLoginButtonClick) | ||
|
|
||
| val event = viewModel.events.first() | ||
| assertThat(event).isEqualTo(LoginEvent.NavigateToGitHubAuth) | ||
| } | ||
|
|
||
| @Test | ||
| fun testOnAction_onUserLoggedIn_emitsNavigateToHomeScreenEvent() = runTest { | ||
| viewModel.onAction(LoginAction.OnUserLoggedIn) | ||
|
|
||
| val event = viewModel.events.first() | ||
| assertThat(event).isEqualTo(LoginEvent.NavigateToHomeScreen) | ||
| } | ||
| } |
81 changes: 81 additions & 0 deletions
81
app/src/androidTest/java/com/notifier/app/auth/presentation/setup/SetupScreenTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package com.notifier.app.auth.presentation.setup | ||
|
|
||
| import androidx.compose.ui.test.assertIsDisplayed | ||
| import androidx.compose.ui.test.junit4.createComposeRule | ||
| import androidx.compose.ui.test.onNodeWithText | ||
| import androidx.compose.ui.test.performClick | ||
| import com.google.common.truth.Truth.assertThat | ||
| import org.junit.Rule | ||
| import org.junit.Test | ||
|
|
||
| class SetupScreenTest { | ||
| @get:Rule | ||
| val composeRule = createComposeRule() | ||
|
|
||
| @Test | ||
| fun testSetupScreen_whenFetchingToken_showsConnectingMessage() { | ||
| composeRule.setContent { | ||
| SetupScreen( | ||
| state = SetupState(setupStep = SetupStep.FETCHING_TOKEN), | ||
| onAction = {} | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Connecting to GitHub…") | ||
| .assertIsDisplayed() | ||
| } | ||
|
|
||
| @Test | ||
| fun testSetupScreen_whenSavingToken_showsSavingMessage() { | ||
| composeRule.setContent { | ||
| SetupScreen( | ||
| state = SetupState(setupStep = SetupStep.SAVING_TOKEN), | ||
| onAction = {} | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Saving user information…") | ||
| .assertIsDisplayed() | ||
| } | ||
|
|
||
| @Test | ||
| fun testSetupScreen_whenSuccess_showsSuccessMessageAndContinueButton_clickTriggersCallback() { | ||
| var capturedAction: SetupAction? = null | ||
|
|
||
| composeRule.setContent { | ||
| SetupScreen( | ||
| state = SetupState(setupStep = SetupStep.SUCCESS), | ||
| onAction = { | ||
| capturedAction = it | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Connected successfully!") | ||
| .assertIsDisplayed() | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Continue") | ||
| .assertIsDisplayed() | ||
| .performClick() | ||
|
|
||
| assertThat(capturedAction).isEqualTo(SetupAction.OnContinueButtonClick) | ||
| } | ||
|
|
||
| @Test | ||
| fun testSetupScreen_whenFailed_showsErrorMessage() { | ||
| composeRule.setContent { | ||
| SetupScreen( | ||
| state = SetupState(setupStep = SetupStep.FAILED), | ||
| onAction = {} | ||
| ) | ||
| } | ||
|
|
||
| composeRule | ||
| .onNodeWithText("Connection failed. Please try again.") | ||
| .assertIsDisplayed() | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.