Skip to content

Commit c101fb8

Browse files
committed
tests
1 parent ba8c91c commit c101fb8

File tree

8 files changed

+238
-382
lines changed

8 files changed

+238
-382
lines changed

app/src/main/java/com/firebase/uidemo/ChooserActivity.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ class ChooserActivity : ComponentActivity() {
113113
)
114114

115115
private val activityItems = listOf(
116-
ActivityEntry(AuthUiActivity::class.java,
117-
R.string.title_auth_activity, R.string.desc_auth),
118116
ActivityEntry(AuthComposeActivity::class.java,
119117
R.string.auth_compose_title, R.string.desc_auth),
120118
ActivityEntry(AnonymousUpgradeActivity::class.java,

auth/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ dependencies {
112112
testImplementation(Config.Libs.Test.core)
113113
testImplementation(Config.Libs.Test.robolectric)
114114
testImplementation(Config.Libs.Provider.facebook)
115+
testImplementation("androidx.compose.ui:ui-test-junit4")
116+
debugImplementation("androidx.compose.ui:ui-test-manifest")
117+
115118

116119
debugImplementation(project(":internal:lintchecks"))
117120
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.firebase.ui.auth.ui.email
2+
3+
import androidx.compose.ui.semantics.SemanticsProperties
4+
import androidx.compose.ui.test.*
5+
import androidx.compose.ui.test.junit4.createComposeRule
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
7+
import com.firebase.ui.auth.data.model.FlowParameters
8+
import com.google.common.truth.Truth.assertThat
9+
import org.junit.Before
10+
import org.junit.Rule
11+
import org.junit.Test
12+
import org.junit.runner.RunWith
13+
14+
/** Matches any node that exposes an `Error` semantics property. */
15+
private fun hasAnyError(): SemanticsMatcher =
16+
SemanticsMatcher("has any error") { node ->
17+
node.config.contains(SemanticsProperties.Error)
18+
}
19+
20+
/**
21+
* UI tests for [CheckEmailScreen] – no Mockito required.
22+
*/
23+
@RunWith(AndroidJUnit4::class)
24+
class CheckEmailScreenTest {
25+
26+
@get:Rule
27+
val composeTestRule = createComposeRule()
28+
29+
private lateinit var flowParameters: FlowParameters
30+
31+
@Before
32+
fun setUp() {
33+
flowParameters = FlowParameters(
34+
appName = "test-app",
35+
providers = emptyList(),
36+
defaultProvider = null,
37+
themeId = 0,
38+
logoId = 0,
39+
termsOfServiceUrl = "https://example.com/terms",
40+
privacyPolicyUrl = "https://example.com/privacy",
41+
enableCredentials = false,
42+
enableAnonymousUpgrade = false,
43+
alwaysShowProviderChoice = true,
44+
lockOrientation = false,
45+
emailLink = null,
46+
passwordResetSettings = null,
47+
authMethodPickerLayout = null
48+
)
49+
}
50+
51+
@Test
52+
fun initialEmail_isDisplayed() {
53+
val initial = "[email protected]"
54+
55+
composeTestRule.setContent {
56+
CheckEmailScreen(
57+
flowParameters = flowParameters,
58+
initialEmail = initial,
59+
onExistingEmailUser = {},
60+
onExistingIdpUser = {},
61+
onNewUser = {},
62+
onDeveloperFailure = {}
63+
)
64+
}
65+
66+
composeTestRule
67+
.onNodeWithText(initial, substring = false, ignoreCase = true)
68+
.assertIsDisplayed()
69+
}
70+
71+
@Test
72+
fun enteringValidEmail_andClickingSignIn_invokesCallback() {
73+
var callbackInvoked = false
74+
75+
composeTestRule.setContent {
76+
CheckEmailScreen(
77+
flowParameters = flowParameters,
78+
onExistingEmailUser = { callbackInvoked = true },
79+
onExistingIdpUser = {},
80+
onNewUser = {},
81+
onDeveloperFailure = {}
82+
)
83+
}
84+
85+
composeTestRule.onNodeWithText("Email", substring = true)
86+
.performTextInput("[email protected]")
87+
88+
composeTestRule.onNodeWithText("Sign in", substring = true)
89+
.performClick()
90+
91+
composeTestRule.waitUntil(timeoutMillis = 2_000) { callbackInvoked }
92+
assertThat(callbackInvoked).isTrue()
93+
}
94+
95+
@Test
96+
fun emptyEmail_andClickingSignUp_setsTextFieldError_andDoesNotInvokeCallback() {
97+
var callbackInvoked = false
98+
99+
composeTestRule.setContent {
100+
CheckEmailScreen(
101+
flowParameters = flowParameters,
102+
onExistingEmailUser = {},
103+
onExistingIdpUser = {},
104+
onNewUser = { callbackInvoked = true },
105+
onDeveloperFailure = {}
106+
)
107+
}
108+
109+
composeTestRule
110+
.onNodeWithText("Sign up", substring = true, ignoreCase = true)
111+
.performClick()
112+
113+
composeTestRule.onNode(hasAnyError()).assertExists()
114+
115+
assertThat(callbackInvoked).isFalse()
116+
}
117+
}

auth/src/test/java/com/firebase/ui/auth/ui/email/EmailActivityTest.java

Lines changed: 0 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -74,104 +74,6 @@ public void testOnCreate_emailLinkNormalFlow_expectCheckEmailFlowStarted() {
7474
emailActivity.getSupportFragmentManager().findFragmentByTag(CheckEmailFragment.TAG);
7575
}
7676

77-
@Test
78-
public void testOnCreate_emailLinkLinkingFlow_expectSendEmailLinkFlowStarted() {
79-
// This is normally done by EmailLinkSendEmailHandler, saving the IdpResponse is done
80-
// in EmailActivity but it will not be saved if we haven't previously set the email
81-
EmailLinkPersistenceManager.getInstance().saveEmail(
82-
ApplicationProvider.getApplicationContext(),
83-
EMAIL, TestConstants.SESSION_ID, TestConstants.UID);
84-
85-
EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER, true, false);
86-
87-
EmailLinkFragment fragment = (EmailLinkFragment) emailActivity
88-
.getSupportFragmentManager().findFragmentByTag(EmailLinkFragment.TAG);
89-
assertThat(fragment).isNotNull();
90-
91-
EmailLinkPersistenceManager persistenceManager = EmailLinkPersistenceManager.getInstance();
92-
IdpResponse response = persistenceManager.retrieveSessionRecord(
93-
ApplicationProvider.getApplicationContext()).getIdpResponseForLinking();
94-
95-
assertThat(response.getProviderType()).isEqualTo(GoogleAuthProvider.PROVIDER_ID);
96-
assertThat(response.getEmail()).isEqualTo(EMAIL);
97-
assertThat(response.getIdpToken()).isEqualTo(ID_TOKEN);
98-
assertThat(response.getIdpSecret()).isEqualTo(SECRET);
99-
}
100-
101-
// @Test TODO(lsirac): uncomment after figuring out why this no longer works
102-
public void testOnTroubleSigningIn_expectTroubleSigningInFragment() {
103-
EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER);
104-
emailActivity.onTroubleSigningIn(EMAIL);
105-
TroubleSigningInFragment fragment = (TroubleSigningInFragment) emailActivity
106-
.getSupportFragmentManager().findFragmentByTag(TroubleSigningInFragment.TAG);
107-
assertThat(fragment).isNotNull();
108-
}
109-
110-
@Test
111-
public void testOnClickResendEmail_expectSendEmailLinkFlowStarted() {
112-
EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER);
113-
emailActivity.onClickResendEmail(EMAIL);
114-
shadowOf(Looper.getMainLooper()).idle();
115-
EmailLinkFragment fragment = (EmailLinkFragment) emailActivity
116-
.getSupportFragmentManager().findFragmentByTag(EmailLinkFragment.TAG);
117-
assertThat(fragment).isNotNull();
118-
}
119-
120-
@Test
121-
public void testSignUpButton_validatesFields() {
122-
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID);
123-
// Trigger RegisterEmailFragment (bypass check email)
124-
emailActivity.onNewUser(
125-
new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());
126-
shadowOf(Looper.getMainLooper()).idle();
127-
Button button = emailActivity.findViewById(R.id.button_create);
128-
button.performClick();
129-
TextInputLayout nameLayout = emailActivity.findViewById(R.id.name_layout);
130-
TextInputLayout passwordLayout = emailActivity.findViewById(R.id.password_layout);
131-
assertEquals(
132-
emailActivity.getString(R.string.fui_missing_first_and_last_name),
133-
nameLayout.getError().toString());
134-
assertEquals(
135-
String.format(
136-
emailActivity.getResources().getQuantityString(
137-
R.plurals.fui_error_weak_password,
138-
R.integer.fui_min_password_length),
139-
emailActivity.getResources()
140-
.getInteger(R.integer.fui_min_password_length)
141-
),
142-
passwordLayout.getError().toString());
143-
}
144-
145-
@Test
146-
public void testSetDefaultEmail_validField() {
147-
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);
148-
CheckEmailFragment fragment = (CheckEmailFragment) emailActivity
149-
.getSupportFragmentManager().findFragmentByTag(CheckEmailFragment.TAG);
150-
assertThat(fragment).isNotNull();
151-
TextInputEditText email = emailActivity.findViewById(R.id.email);
152-
assertEquals(TestConstants.EMAIL, email.getText().toString());
153-
}
154-
155-
@Test
156-
public void testSetDefaultEmail_expectWelcomeBackPasswordPrompt() {
157-
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);
158-
emailActivity.onExistingEmailUser(new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());
159-
ShadowActivity.IntentForResult nextIntent =
160-
Shadows.shadowOf(emailActivity).getNextStartedActivityForResult();
161-
assertEquals(WelcomeBackPasswordPrompt.class.getName(),
162-
nextIntent.intent.getComponent().getClassName());
163-
}
164-
165-
@Test
166-
public void testSetDefaultEmail_expectRegisterEmailFragment() {
167-
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);
168-
emailActivity.onNewUser(new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());
169-
shadowOf(Looper.getMainLooper()).idle();
170-
RegisterEmailFragment registerEmailFragment = (RegisterEmailFragment) emailActivity
171-
.getSupportFragmentManager().findFragmentByTag(RegisterEmailFragment.TAG);
172-
assertThat(registerEmailFragment).isNotNull();
173-
}
174-
17577
private EmailActivity createActivity(String providerId) {
17678
return createActivity(providerId, false, false);
17779
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package com.firebase.ui.auth.ui.email
2+
3+
import androidx.compose.ui.semantics.SemanticsProperties
4+
import androidx.compose.ui.test.*
5+
import androidx.compose.ui.test.junit4.createComposeRule
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
7+
import com.firebase.ui.auth.data.model.FlowParameters
8+
import com.firebase.ui.auth.data.model.User
9+
import com.google.common.truth.Truth.assertThat
10+
import com.google.firebase.auth.EmailAuthProvider
11+
import org.junit.Before
12+
import org.junit.Rule
13+
import org.junit.Test
14+
import org.junit.runner.RunWith
15+
16+
private fun hasAnyError(): SemanticsMatcher =
17+
SemanticsMatcher("has any error") { it.config.contains(SemanticsProperties.Error) }
18+
19+
private val signUpButton = hasText("Sign up", ignoreCase = true).and(hasClickAction())
20+
21+
22+
@RunWith(AndroidJUnit4::class)
23+
class RegisterEmailScreenTest {
24+
25+
@get:Rule
26+
val composeTestRule = createComposeRule()
27+
28+
private lateinit var flowParameters: FlowParameters
29+
30+
@Before
31+
fun setUp() {
32+
flowParameters = FlowParameters(
33+
appName = "test-app",
34+
providers = emptyList(),
35+
defaultProvider = null,
36+
themeId = 0,
37+
logoId = 0,
38+
termsOfServiceUrl = "https://example.com/terms",
39+
privacyPolicyUrl = "https://example.com/privacy",
40+
enableCredentials = false,
41+
enableAnonymousUpgrade = false,
42+
alwaysShowProviderChoice = true,
43+
lockOrientation = false,
44+
emailLink = null,
45+
passwordResetSettings = null,
46+
authMethodPickerLayout = null
47+
)
48+
}
49+
50+
@Test
51+
fun initialEmailAndName_areDisplayed() {
52+
val initialUser = User.Builder(EmailAuthProvider.PROVIDER_ID, "[email protected]")
53+
.setName("Alice")
54+
.build()
55+
56+
composeTestRule.setContent {
57+
RegisterEmailScreen(
58+
flowParameters = flowParameters,
59+
user = initialUser,
60+
onRegisterSuccess = { _, _ -> },
61+
onRegisterError = {}
62+
)
63+
}
64+
65+
composeTestRule.onNodeWithText("[email protected]", substring = false, ignoreCase = true)
66+
.assertIsDisplayed()
67+
composeTestRule.onNodeWithText("Alice", substring = false, ignoreCase = true)
68+
.assertIsDisplayed()
69+
}
70+
71+
@Test
72+
fun enteringValidData_andClickingSignUp_invokesCallback() {
73+
var callbackInvoked = false
74+
75+
composeTestRule.setContent {
76+
RegisterEmailScreen(
77+
flowParameters = flowParameters,
78+
user = User.Builder(EmailAuthProvider.PROVIDER_ID, "").build(),
79+
onRegisterSuccess = { _, _ -> callbackInvoked = true },
80+
onRegisterError = {}
81+
)
82+
}
83+
84+
composeTestRule.onNodeWithText("Email", substring = true)
85+
.performTextInput("[email protected]")
86+
composeTestRule.onNodeWithText("Name", substring = true, ignoreCase = true)
87+
.performTextInput("Bob")
88+
composeTestRule.onNodeWithText("Password", substring = true)
89+
.performTextInput("password123")
90+
91+
composeTestRule.onNode(signUpButton).performClick()
92+
93+
composeTestRule.waitUntil(timeoutMillis = 2_000) { callbackInvoked }
94+
assertThat(callbackInvoked).isTrue()
95+
}
96+
97+
@Test
98+
fun emptyForm_andClickingSignUp_setsError_andDoesNotInvokeCallback() {
99+
var callbackInvoked = false
100+
101+
composeTestRule.setContent {
102+
RegisterEmailScreen(
103+
flowParameters = flowParameters,
104+
user = User.Builder(EmailAuthProvider.PROVIDER_ID, "").build(),
105+
onRegisterSuccess = { _, _ -> callbackInvoked = true },
106+
onRegisterError = {}
107+
)
108+
}
109+
110+
composeTestRule.onNode(signUpButton).performClick()
111+
112+
composeTestRule
113+
.onNode(hasText("Email", ignoreCase = true).and(hasAnyError()))
114+
.assertExists()
115+
116+
assertThat(callbackInvoked).isFalse()
117+
}
118+
}

0 commit comments

Comments
 (0)