Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into build/update-compose-…
Browse files Browse the repository at this point in the history
…kotlin
  • Loading branch information
levinzonr committed May 21, 2024
2 parents ef1bac2 + 7d7d34c commit 6d46116
Show file tree
Hide file tree
Showing 11 changed files with 521 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
run: ./gradlew detekt

- name: Run Tests
run: ./gradlew test
run: ./gradlew testDevDebugUnitTest
13 changes: 11 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@file:Suppress("UnstableApiUsage")

// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
Expand Down Expand Up @@ -52,9 +53,16 @@ android {
}
}

testOptions.unitTests {
isIncludeAndroidResources = true
}

packaging {
resources.excludes.add("META-INF/versions/9/previous-compilation-data.bin")
resources {
excludes.add("META-INF/versions/9/previous-compilation-data.bin")
excludes.add("META-INF/LICENSE.md")
excludes.add("META-INF/LICENSE-notice.md")
}
}
}

Expand Down Expand Up @@ -95,7 +103,7 @@ dependencies {
implementation(libs.android.activity.compose)
implementation(libs.android.lifecycle.viewmodel.compose)
implementation(libs.bundles.google.accompanist)
implementation (libs.android.compose.ui.tooling.preview)
implementation(libs.android.compose.ui.tooling.preview)
debugImplementation(libs.android.compose.ui.tooling)

// Injection
Expand All @@ -114,4 +122,5 @@ dependencies {
releaseImplementation(libs.chucker.noop)
testImplementation(libs.bundles.test)
androidTestImplementation(libs.bundles.android.test)
debugImplementation(libs.android.compose.ui.test.manifest)
}
22 changes: 0 additions & 22 deletions app/src/androidTest/java/com/monstarlab/ExampleInstrumentedTest.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,30 @@ fun LoginScreen(state: LoginState = LoginState(), actions: LoginActions = LoginA
AppTextField(
value = state.email,
onValueChange = actions.onEmailChange,
modifier = Modifier.fillMaxWidth(),
placeholder = "E-Mail",
label = "E-Mail",
modifier = Modifier.fillMaxWidth(),
)

Spacer(modifier = Modifier.size(Theme.dimensions.medium3))

AppTextField(
value = state.password,
onValueChange = actions.onPasswordChange,
modifier = Modifier.fillMaxWidth(),
error = state.error?.displayableMessage,
visualTransformation = PasswordVisualTransformation(),
placeholder = "Password",
label = "Password",
modifier = Modifier.fillMaxWidth(),
)

Spacer(modifier = Modifier.size(Theme.dimensions.medium3))

AppButton(
text = "Login",
onClick = actions.onLoginClick,
modifier = Modifier.fillMaxWidth(),
isLoading = state.isLoading,
modifier = Modifier.fillMaxWidth(),
)
}
}
Expand Down
16 changes: 0 additions & 16 deletions app/src/test/java/com/monstarlab/ExampleUnitTest.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.monstarlab.features.login.domain.usecase

import com.monstarlab.features.auth.domain.models.AuthToken
import com.monstarlab.features.auth.domain.repository.AuthRepository
import com.monstarlab.features.user.domain.repository.UserRepository
import io.mockk.clearAllMocks
import io.mockk.coEvery
import io.mockk.mockk
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import kotlinx.coroutines.test.runTest

class LoginUseCaseTest {

private lateinit var authRepository: AuthRepository
private lateinit var userRepository: UserRepository
private lateinit var loginUseCase: LoginUseCase

@Before
fun setUp() {
authRepository = mockk()
userRepository = mockk()
loginUseCase = LoginUseCase(authRepository, userRepository)
}

@After
fun tearDown() {
clearAllMocks()
}

/**
* GIVEN
* - Auth token is returned
* - Retrieving user is returned
* WHEN
* - User logs in
* THEN
* - Result is successful
*/
@Test
fun testLoginSuccess() = runTest {
// GIVEN
val email = "[email protected]"
val password = "password"

coEvery { authRepository.login(email, password) } returns AuthToken("token")
coEvery { userRepository.get() } returns mockk()

// WHEN
val result = loginUseCase.invoke(email, password)

// THEN
assertEquals("Result is successful", true, result.isSuccess)
}

/**
* GIVEN
* - Auth token throws an exception
* - Retrieving user is returned
* WHEN
* - User logs in
* THEN
* - Result is unsuccessful
*/
@Test
fun testLoginFailure() = runTest {
// GIVEN
val email = "[email protected]"
val password = "password"

coEvery { authRepository.login(email, password) } throws Exception()
coEvery { userRepository.get() } returns mockk()

// WHEN
val result = loginUseCase.invoke(email, password)

// THEN
assertEquals("Result is unsuccessful", false, result.isSuccess)
}

/**
* GIVEN
* - Auth token is returned
* - Retrieving user throws an exception
* WHEN
* - User logs in
* THEN
* - Result is unsuccessful
*/
@Test
fun testLoginFailureWhenUserRetrievalFails() = runTest {
// GIVEN
val email = "[email protected]"
val password = "password"

coEvery { authRepository.login(email, password) } returns AuthToken("token")
coEvery { userRepository.get() } throws Exception()

// WHEN
val result = loginUseCase.invoke(email, password)

// THEN
assertEquals("Result is unsuccessful", false, result.isSuccess)
}
}
116 changes: 116 additions & 0 deletions app/src/test/java/com/monstarlab/features/login/ui/LoginScreenTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.monstarlab.features.login.ui

import androidx.compose.ui.test.assert
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.hasClickAction
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextReplacement
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.mockk
import io.mockk.verify
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class LoginScreenTest {

@get:Rule
val composeTestRule = createComposeRule()

private val mockActions: LoginActions = mockk(relaxed = true)

@Before
fun setUp() {
composeTestRule.setContent {
LoginScreen(state = LoginState(), actions = mockActions)
}
}

/**
* GIVEN:
* - Initial state of the login screen
* WHEN:
* - The screen is displayed
* THEN:
* - Email field should be enabled, displayed, and contain "[email protected]"
* - Password field should be enabled and displayed
* - Login button should be enabled and displayed
*/
@Test
fun testInitialState() {
composeTestRule
.onNodeWithText("E-Mail")
.assertIsEnabled()
.assertIsDisplayed()
.assert(hasText("[email protected]"))

composeTestRule
.onNodeWithText("Password")
.assertIsEnabled()
.assertIsDisplayed()

composeTestRule
.onNode(hasText("Login") and hasClickAction())
.assertIsEnabled()
.assertIsDisplayed()
}

/**
* GIVEN:
* - Initial email is "[email protected]"
* - Test email is "[email protected]"
* WHEN:
* - User types "[email protected]" into the email field
* THEN:
* - onEmailChange action should be called with "[email protected]"
*/
@Test
fun testEmailInput() {
composeTestRule
.onNodeWithText("E-Mail")
.performTextReplacement("[email protected]")

verify { mockActions.onEmailChange("[email protected]") }
}

/**
* GIVEN:
* - Initial password is empty
* - Test password is "secret"
* WHEN:
* - User types "secret" into the password field
* THEN:
* - onPasswordChange action should be called with "secret"
*/
@Test
fun testPasswordInput() {
composeTestRule
.onNodeWithText("Password")
.performTextReplacement("secret")

verify { mockActions.onPasswordChange("secret") }
}

/**
* GIVEN:
* - User is on the login screen
* WHEN:
* - User clicks the login button
* THEN:
* - onLoginClick action should be called
*/
@Test
fun testLoginButtonClick() {
composeTestRule
.onNode(hasText("Login") and hasClickAction())
.performClick()

verify { mockActions.onLoginClick() }
}
}
Loading

0 comments on commit 6d46116

Please sign in to comment.