@@ -22,20 +22,24 @@ import com.amplifyframework.auth.cognito.testUtil.withSignUpEvent
2222import com.amplifyframework.auth.result.AuthSignUpResult
2323import com.amplifyframework.auth.result.step.AuthNextSignUpStep
2424import com.amplifyframework.auth.result.step.AuthSignUpStep
25+ import com.amplifyframework.statemachine.codegen.data.SignUpData
2526import com.amplifyframework.statemachine.codegen.events.SignUpEvent
2627import com.amplifyframework.statemachine.codegen.states.AuthState
2728import com.amplifyframework.statemachine.codegen.states.AuthenticationState
2829import com.amplifyframework.statemachine.codegen.states.SignUpState
2930import io.kotest.assertions.throwables.shouldThrowAny
31+ import io.kotest.matchers.nulls.shouldBeNull
3032import io.kotest.matchers.shouldBe
3133import io.mockk.coEvery
3234import io.mockk.coVerify
3335import io.mockk.every
3436import io.mockk.justRun
3537import io.mockk.mockk
3638import kotlinx.coroutines.ExperimentalCoroutinesApi
39+ import kotlinx.coroutines.async
3740import kotlinx.coroutines.flow.MutableStateFlow
3841import kotlinx.coroutines.launch
42+ import kotlinx.coroutines.test.TestScope
3943import kotlinx.coroutines.test.runCurrent
4044import kotlinx.coroutines.test.runTest
4145import org.junit.Test
@@ -50,6 +54,14 @@ class ConfirmSignUpUseCaseTest {
5054 }
5155 private val useCase = ConfirmSignUpUseCase (stateMachine = stateMachine)
5256
57+ private val signUpData = SignUpData (
58+ username = " username" ,
59+ validationData = mapOf (" key" to " value" ),
60+ clientMetadata = mapOf (" meta" to " data" ),
61+ session = " session" ,
62+ userId = " userId"
63+ )
64+
5365 @Test
5466 fun `fails if not configured` () = runTest {
5567 val expectedAuthError = InvalidUserPoolConfigurationException ()
@@ -75,30 +87,96 @@ class ConfirmSignUpUseCaseTest {
7587
7688 runCurrent()
7789 stateFlow.emit(mockAuthState(SignUpState .ConfirmingSignUp (mockk())))
78- stateFlow.emit(mockAuthState(SignUpState .Error (exception)))
90+ stateFlow.emit(mockAuthState(SignUpState .Error (mockk(), exception)))
7991 }
8092
8193 @Test
8294 fun `sends expected event` () = runTest {
8395 coEvery { stateMachine.getCurrentState().authNState } returns AuthenticationState .Configured ()
8496 coEvery { stateMachine.getCurrentState().authSignUpState } returns null
8597
86- launch {
87- useCase.execute(" user" , " pass" )
98+ executeUseCaseToCompletion()
99+
100+ coVerify {
101+ stateMachine.send(
102+ withSignUpEvent<SignUpEvent .EventType .ConfirmSignUp > { event ->
103+ event.signUpData.username shouldBe " user"
104+ event.confirmationCode shouldBe " pass"
105+ }
106+ )
107+ }
108+ }
88109
89- coVerify {
90- stateMachine.send(
91- withSignUpEvent<SignUpEvent .EventType .ConfirmSignUp > { event ->
92- event.signUpData.username shouldBe " user"
93- event.confirmationCode shouldBe " pass"
110+ @Test
111+ fun `uses signUpData values from existing error state` () = runTest {
112+ coEvery { stateMachine.getCurrentState().authNState } returns AuthenticationState .Configured ()
113+ coEvery { stateMachine.getCurrentState().authSignUpState } returns
114+ SignUpState .Error (signUpData = signUpData, exception = mockk())
115+
116+ executeUseCaseToCompletion(username = signUpData.username)
117+
118+ coVerify {
119+ stateMachine.send(
120+ withSignUpEvent<SignUpEvent .EventType .ConfirmSignUp > { event ->
121+ event.signUpData.run {
122+ username shouldBe signUpData.username
123+ validationData shouldBe signUpData.validationData
124+ clientMetadata.shouldBeNull() // was not passed in options
125+ session shouldBe signUpData.session
126+ userId shouldBe signUpData.userId
94127 }
95- )
96- }
128+ event.confirmationCode shouldBe " pass"
129+ }
130+ )
97131 }
132+ }
98133
99- runCurrent()
100- stateFlow.emit(mockAuthState(SignUpState .ConfirmingSignUp (mockk())))
101- stateFlow.emit(mockAuthState(SignUpState .SignedUp (mockk(), mockk())))
134+ @Test
135+ fun `uses session value from existing AwaitingConfirmation state` () = runTest {
136+ coEvery { stateMachine.getCurrentState().authNState } returns AuthenticationState .Configured ()
137+ coEvery { stateMachine.getCurrentState().authSignUpState } returns
138+ SignUpState .AwaitingUserConfirmation (signUpData = signUpData, signUpResult = mockk())
139+
140+ executeUseCaseToCompletion(username = signUpData.username)
141+
142+ coVerify {
143+ stateMachine.send(
144+ withSignUpEvent<SignUpEvent .EventType .ConfirmSignUp > { event ->
145+ event.signUpData.run {
146+ username shouldBe signUpData.username
147+ validationData shouldBe signUpData.validationData
148+ clientMetadata.shouldBeNull() // was not passed in options
149+ session shouldBe signUpData.session
150+ userId shouldBe signUpData.userId
151+ }
152+ event.confirmationCode shouldBe " pass"
153+ }
154+ )
155+ }
156+ }
157+
158+ @Test
159+ fun `does not use values from existing state if username does not match` () = runTest {
160+ coEvery { stateMachine.getCurrentState().authNState } returns AuthenticationState .Configured ()
161+ coEvery { stateMachine.getCurrentState().authSignUpState } returns
162+ SignUpState .AwaitingUserConfirmation (signUpData = signUpData, signUpResult = mockk())
163+
164+ executeUseCaseToCompletion(username = " bob" )
165+
166+ coVerify {
167+ stateMachine.send(
168+ withSignUpEvent<SignUpEvent .EventType .ConfirmSignUp > { event ->
169+ event.signUpData.run {
170+ username shouldBe " bob"
171+ validationData.shouldBeNull()
172+ clientMetadata.shouldBeNull() // was not passed in options
173+ session.shouldBeNull()
174+ userId.shouldBeNull()
175+ }
176+ event.confirmationCode shouldBe " pass"
177+ }
178+ )
179+ }
102180 }
103181
104182 @Test
@@ -116,17 +194,24 @@ class ConfirmSignUpUseCaseTest {
116194 coEvery { stateMachine.getCurrentState().authNState } returns AuthenticationState .Configured ()
117195 coEvery { stateMachine.getCurrentState().authSignUpState } returns null
118196
119- launch {
120- val result = useCase.execute(" user" , " pass" )
121- result shouldBe expectedResult
122- }
123-
124- runCurrent()
125- stateFlow.emit(mockAuthState(SignUpState .ConfirmingSignUp (mockk())))
126- stateFlow.emit(mockAuthState(SignUpState .SignedUp (mockk(), expectedResult)))
197+ val result = executeUseCaseToCompletion(signUpResult = expectedResult)
198+ result shouldBe expectedResult
127199 }
128200
129201 private fun mockAuthState (signUpState : SignUpState ): AuthState = mockk {
130202 coEvery { authSignUpState } returns signUpState
131203 }
204+
205+ @Suppress(" SuspendFunctionOnCoroutineScope" )
206+ private suspend fun TestScope.executeUseCaseToCompletion (
207+ username : String = "user",
208+ confirmationCode : String = "pass",
209+ signUpResult : AuthSignUpResult = mockk()
210+ ): AuthSignUpResult {
211+ val result = async { useCase.execute(username, confirmationCode) }
212+ runCurrent()
213+ stateFlow.emit(mockAuthState(SignUpState .ConfirmingSignUp (mockk())))
214+ stateFlow.emit(mockAuthState(SignUpState .SignedUp (mockk(), signUpResult)))
215+ return result.await()
216+ }
132217}
0 commit comments