From 86c34ffcda6cfd87ff95cc13df5a74411cf13798 Mon Sep 17 00:00:00 2001 From: Ademola Fadumo <48495111+demolaf@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:53:30 +0100 Subject: [PATCH] fix(auth): validate display name only when required in sign-up form (#2383) * fix(auth): validate display name only when required in sign-up form * fix(auth): use locale-safe matcher for sign-up button in test --- .../ui/auth/ui/screens/email/SignUpUI.kt | 2 +- .../ui/auth/ui/screens/email/SignUpUITest.kt | 115 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 auth/src/test/java/com/firebase/ui/auth/ui/screens/email/SignUpUITest.kt diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/screens/email/SignUpUI.kt b/auth/src/main/java/com/firebase/ui/auth/ui/screens/email/SignUpUI.kt index dfc413bc6..6ff0d19f4 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/screens/email/SignUpUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/ui/screens/email/SignUpUI.kt @@ -95,7 +95,7 @@ fun SignUpUI( val isFormValid = remember(displayName, email, password, confirmPassword) { derivedStateOf { listOf( - displayNameValidator.validate(displayName), + !provider.isDisplayNameRequired || displayNameValidator.validate(displayName), emailValidator.validate(email), passwordValidator.validate(password), confirmPasswordValidator.validate(confirmPassword) diff --git a/auth/src/test/java/com/firebase/ui/auth/ui/screens/email/SignUpUITest.kt b/auth/src/test/java/com/firebase/ui/auth/ui/screens/email/SignUpUITest.kt new file mode 100644 index 000000000..ac642adb7 --- /dev/null +++ b/auth/src/test/java/com/firebase/ui/auth/ui/screens/email/SignUpUITest.kt @@ -0,0 +1,115 @@ +/* + * Copyright 2025 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.firebase.ui.auth.ui.screens.email + +import android.content.Context +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +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.performTextInput +import androidx.test.core.app.ApplicationProvider +import com.firebase.ui.auth.configuration.authUIConfiguration +import com.firebase.ui.auth.configuration.auth_provider.AuthProvider +import com.firebase.ui.auth.configuration.string_provider.AuthUIStringProvider +import com.firebase.ui.auth.configuration.string_provider.DefaultAuthUIStringProvider +import com.firebase.ui.auth.configuration.string_provider.LocalAuthUIStringProvider +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +/** + * Unit tests for [SignUpUI], covering form validity logic. + * + * @suppress Internal test class + */ +@Config(sdk = [34]) +@RunWith(RobolectricTestRunner::class) +class SignUpUITest { + + @get:Rule + val composeTestRule = createComposeRule() + + private lateinit var applicationContext: Context + private lateinit var stringProvider: AuthUIStringProvider + + @Before + fun setUp() { + applicationContext = ApplicationProvider.getApplicationContext() + stringProvider = DefaultAuthUIStringProvider(applicationContext) + } + + @Test + fun `sign up button becomes enabled when display name is not required and hidden`() { + val provider = AuthProvider.Email( + isDisplayNameRequired = false, + emailLinkActionCodeSettings = null, + passwordValidationRules = emptyList() + ) + val configuration = authUIConfiguration { + context = applicationContext + providers { provider(provider) } + } + + composeTestRule.setContent { + CompositionLocalProvider(LocalAuthUIStringProvider provides stringProvider) { + var email by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + var confirmPassword by remember { mutableStateOf("") } + + SignUpUI( + configuration = configuration, + isLoading = false, + displayName = "", + email = email, + password = password, + confirmPassword = confirmPassword, + onDisplayNameChange = { }, + onEmailChange = { email = it }, + onPasswordChange = { password = it }, + onConfirmPasswordChange = { confirmPassword = it }, + onGoToSignIn = { }, + onSignUpClick = { } + ) + } + } + + // Name field should not be rendered since it isn't required. + composeTestRule.onNodeWithText(stringProvider.nameHint).assertDoesNotExist() + + composeTestRule.onNodeWithText(stringProvider.emailHint) + .performTextInput("test@example.com") + composeTestRule.onNodeWithText(stringProvider.passwordHint) + .performTextInput("Password123") + composeTestRule.onNodeWithText(stringProvider.confirmPasswordHint) + .performTextInput("Password123") + + composeTestRule.waitForIdle() + + // With email/password/confirmPassword all valid and no display name required, + // the sign up button should be enabled even though displayName is still "". + composeTestRule.onNode(hasText(stringProvider.signupPageTitle.uppercase()) and hasClickAction()) + .assertIsEnabled() + } +}