Skip to content

Commit

Permalink
Merge pull request #48 from snuhcs-course/integration-test/frontend
Browse files Browse the repository at this point in the history
Implement Integration test
  • Loading branch information
JH747 authored Nov 21, 2023
2 parents 4715dfa + 7ae6206 commit 05e1848
Show file tree
Hide file tree
Showing 13 changed files with 956 additions and 19 deletions.
10 changes: 9 additions & 1 deletion frontend/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ android {
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner = "com.example.speechbuddy.CustomTestRunner"
vectorDrawables {
useSupportLibrary = true
}
Expand Down Expand Up @@ -68,6 +68,7 @@ dependencies {
testImplementation("androidx.arch.core:core-testing:2.2.0")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.4.0")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
Expand Down Expand Up @@ -134,6 +135,13 @@ dependencies {
val hiltVersion = "2.48.1"
implementation("com.google.dagger:hilt-android:$hiltVersion")
kapt("com.google.dagger:hilt-compiler:$hiltVersion")
testImplementation("com.google.dagger:hilt-android-testing:$hiltVersion")
androidTestImplementation("com.google.dagger:hilt-android-testing:$hiltVersion")
kapt("com.google.dagger:hilt-android-compiler:$hiltVersion")
kaptTest("com.google.dagger:hilt-android-compiler:$hiltVersion")
kaptAndroidTest("com.google.dagger:hilt-android-compiler:$hiltVersion")
testAnnotationProcessor("com.google.dagger:hilt-android-compiler:2.44")
androidTestAnnotationProcessor("com.google.dagger:hilt-android-compiler:2.44")

implementation("androidx.hilt:hilt-navigation-compose:1.1.0")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.speechbuddy

import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import dagger.hilt.android.testing.HiltTestApplication

class CustomTestRunner : AndroidJUnitRunner() {

override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.example.speechbuddy

import androidx.activity.compose.setContent
import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import com.example.speechbuddy.compose.emailverification.EmailVerificationScreen
import com.example.speechbuddy.ui.SpeechBuddyTheme
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@HiltAndroidTest
class EmailVerificationScreenForResetPWTest {

@get:Rule(order = 0)
var hiltRule = HiltAndroidRule(this)

@get:Rule(order = 1)
val composeTestRule = createAndroidComposeRule<AuthActivity>()

@Before
fun setUp() {
hiltRule.inject()
composeTestRule.activity.setContent {
val fakeSource = "reset_password"
SpeechBuddyTheme {
EmailVerificationScreen(
source = fakeSource,
navigateCallback = {}
)
}
}
}

@Test
fun should_display_all_elements_when_emailverification_screen_appears() {
composeTestRule.onNodeWithText(RESET_PASSWORD).assertIsDisplayed()
composeTestRule.onNodeWithText(VERIFY_EMAIL_FOR_RESET_PASSWORD).assertIsDisplayed()
composeTestRule.onNodeWithText(EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(SEND_CODE).assertIsDisplayed().assertHasClickAction().assertIsEnabled()
composeTestRule.onNodeWithText(CODE).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

// email related
@Test
fun should_display_no_email_error_message_after_clicking_send_code_with_no_input() {
composeTestRule.onNodeWithText(SEND_CODE).performClick()
composeTestRule.onNodeWithText(NO_EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

@Test
fun should_display_wrong_email_error_message_after_clicking_send_code_with_invalid_email() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(INVALID_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
composeTestRule.onNodeWithText(WRONG_EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

@Test
fun should_display_unregistered_error_message_after_clicking_send_code_with_unregistered_email() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(UNREGISTERED_EMAIL_EXAMPLE)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
// wait for server's response
Thread.sleep(5000)

composeTestRule.onNodeWithText(UNREGISTERED_EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

@Test
fun should_enable_next_button_and_disable_email_field_after_clicking_send_code_with_valid_email() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(REGISTERED_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()

// wait for email to be sent
Thread.sleep(10000)

composeTestRule.onNodeWithText(CODE_SUCCESSFULLY_SENT).assertIsDisplayed()
composeTestRule.onNodeWithText(EMAIL).assertIsDisplayed().assertIsNotEnabled()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsEnabled()
}

// code related
@Test
fun should_display_no_code_error_message_after_clicking_send_code_with_empty_code() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(REGISTERED_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
// wait for email to be sent
Thread.sleep(10000)

composeTestRule.onNodeWithText(NEXT).performClick()
composeTestRule.onNodeWithText(NO_CODE).assertIsDisplayed()
}

@Test
fun should_display_wrong_code_error_message_after_clicking_send_code_with_wrong_code() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(REGISTERED_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
// wait for email to be sent
Thread.sleep(10000)

composeTestRule.onNodeWithText(CODE).performTextInput(INVALID_CODE)
composeTestRule.onNodeWithText(NEXT).performClick()
composeTestRule.onNodeWithText(WRONG_CODE).assertIsDisplayed()
}

companion object {
const val RESET_PASSWORD = "비밀번호 변경"
const val VERIFY_EMAIL_FOR_RESET_PASSWORD = "비밀번호 변경을 위해 이메일 인증을 먼저 진행해주세요"
const val EMAIL = "이메일"
const val SEND_CODE = "인증번호 발송"
const val CODE = "인증번호"
const val NEXT = "다음"
const val CODE_SUCCESSFULLY_SENT = "인증번호를 발송했습니다"

// error or qualification messages
const val NO_EMAIL = "이메일 주소를 입력해주세요"
const val WRONG_EMAIL = "이메일 주소가 올바르지 않습니다"
const val UNREGISTERED_EMAIL = "등록되지 않은 이메일입니다"
const val NO_CODE = "인증번호를 입력해주세요"
const val WRONG_CODE = "인증번호가 올바르지 않습니다"

// inputs
const val INVALID_EMAIL = "invalidemail"
const val UNREGISTERED_EMAIL_EXAMPLE = "[email protected]"
const val REGISTERED_EMAIL = "[email protected]"
const val INVALID_CODE = "invalid"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.example.speechbuddy

import androidx.activity.compose.setContent
import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import com.example.speechbuddy.compose.emailverification.EmailVerificationScreen
import com.example.speechbuddy.ui.SpeechBuddyTheme
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@HiltAndroidTest
class EmailVerificationScreenForSignupTest {

@get:Rule(order = 0)
var hiltRule = HiltAndroidRule(this)

@get:Rule(order = 1)
val composeTestRule = createAndroidComposeRule<AuthActivity>()

@Before
fun setUp() {
hiltRule.inject()
composeTestRule.activity.setContent {
val fakeSource = "signup"
SpeechBuddyTheme {
EmailVerificationScreen(
source = fakeSource,
navigateCallback = {}
)
}
}
}

@Test
fun should_display_all_elements_when_emailverification_screen_appears() {
composeTestRule.onNodeWithText(SIGNUP).assertIsDisplayed()
composeTestRule.onNodeWithText(VERIFY_EMAIL_FOR_SIGNUP).assertIsDisplayed()
composeTestRule.onNodeWithText(EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(SEND_CODE).assertIsDisplayed().assertHasClickAction().assertIsEnabled()
composeTestRule.onNodeWithText(CODE).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

// email related
@Test
fun should_display_no_email_error_message_after_clicking_send_code_with_no_input() {
composeTestRule.onNodeWithText(SEND_CODE).performClick()
composeTestRule.onNodeWithText(NO_EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

@Test
fun should_display_wrong_email_error_message_after_clicking_send_code_with_invalid_email() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(INVALID_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
composeTestRule.onNodeWithText(WRONG_EMAIL).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

@Test
fun should_display_email_already_taken_error_message_after_clicking_send_code_with_already_taken_email() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(ALREADY_TAKEN_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
// wait for server's response
Thread.sleep(5000)

composeTestRule.onNodeWithText(EMAIL_ALREADY_TAKEN).assertIsDisplayed()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsNotEnabled()
}

@Test
fun should_enable_next_button_and_disable_email_field_after_clicking_send_code_with_valid_email() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(VALID_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()

// wait for email to be sent
Thread.sleep(10000)

composeTestRule.onNodeWithText(CODE_SUCCESSFULLY_SENT).assertIsDisplayed()
composeTestRule.onNodeWithText(EMAIL).assertIsDisplayed().assertIsNotEnabled()
composeTestRule.onNodeWithText(NEXT).assertIsDisplayed().assertHasClickAction().assertIsEnabled()
}

// code related
@Test
fun should_display_no_code_error_message_after_clicking_send_code_with_empty_code() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(VALID_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
// wait for email to be sent
Thread.sleep(10000)

composeTestRule.onNodeWithText(NEXT).performClick()
composeTestRule.onNodeWithText(NO_CODE).assertIsDisplayed()
}

@Test
fun should_display_wrong_code_error_message_after_clicking_send_code_with_wrong_code() {
composeTestRule.onNodeWithText(EMAIL).performTextInput(VALID_EMAIL)
composeTestRule.onNodeWithText(SEND_CODE).performClick()
// wait for email to be sent
Thread.sleep(10000)

composeTestRule.onNodeWithText(CODE).performTextInput(INVALID_CODE)
composeTestRule.onNodeWithText(NEXT).performClick()
composeTestRule.onNodeWithText(WRONG_CODE).assertIsDisplayed()
}

companion object {
const val SIGNUP = "회원가입"
const val VERIFY_EMAIL_FOR_SIGNUP = "회원가입을 위해 이메일 인증을 먼저 진행해주세요"
const val EMAIL = "이메일"
const val SEND_CODE = "인증번호 발송"
const val CODE = "인증번호"
const val NEXT = "다음"
const val CODE_SUCCESSFULLY_SENT = "인증번호를 발송했습니다"

// error or qualification messages
const val NO_EMAIL = "이메일 주소를 입력해주세요"
const val WRONG_EMAIL = "이메일 주소가 올바르지 않습니다"
const val EMAIL_ALREADY_TAKEN = "다른 사용자가 이미 사용하고 있는 이메일입니다"
const val NO_CODE = "인증번호를 입력해주세요"
const val WRONG_CODE = "인증번호가 올바르지 않습니다"

// inputs
const val INVALID_EMAIL = "invalidemail"
const val ALREADY_TAKEN_EMAIL = "[email protected]"
const val VALID_EMAIL = "[email protected]"
const val INVALID_CODE = "invalid"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.example.speechbuddy

import androidx.activity.compose.setContent
import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import com.example.speechbuddy.compose.landing.LandingScreen
import com.example.speechbuddy.ui.SpeechBuddyTheme
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@HiltAndroidTest
class LandingScreenTest {

@get:Rule(order = 0)
var hiltRule = HiltAndroidRule(this)

@get:Rule(order = 1)
val composeTestRule = createAndroidComposeRule<AuthActivity>()

@Before
fun setUp() {
hiltRule.inject()
composeTestRule.activity.setContent {
SpeechBuddyTheme {
LandingScreen( onLoginClick = {})
}
}
}

@Test
fun should_display_guest_mode_and_login_buttons_when_landing_screen_appears() {
composeTestRule.onNodeWithText(GUEST_MODE_ACTION).assertIsDisplayed().assertHasClickAction()
composeTestRule.onNodeWithText(LOGIN_ACTION).assertIsDisplayed().assertHasClickAction()
}

companion object {
const val GUEST_MODE_ACTION = "게스트 모드로 시작하기"
const val LOGIN_ACTION = "로그인하기"
}

}
Loading

0 comments on commit 05e1848

Please sign in to comment.