amplify-swift/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/ClientBehaviorTests/AWSAuthResendSignUpCodeAPIT...

558 lines
24 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Foundation
import XCTest
import AWSCognitoIdentity
@testable import Amplify
@testable import AWSCognitoAuthPlugin
import AWSCognitoIdentityProvider
class AWSAuthResendSignUpCodeAPITests: AWSCognitoAuthClientBehaviorTests {
override func setUp() {
super.setUp()
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
ResendConfirmationCodeOutputResponse(codeDeliveryDetails: .init())
}
)
}
/// Test resendSignUpCode operation can be invoked
///
/// - Given: Given a configured auth plugin
/// - When:
/// - I call resendSignUpCode operation
/// - Then:
/// - I should get a valid operation object
///
func testResendSignupCodeRequest() async throws {
let pluginOptions = ["somekey": "somevalue"]
let options = AuthResendSignUpCodeRequest.Options(pluginOptions: pluginOptions)
_ = try await plugin.resendSignUpCode(for: "username", options: options)
}
/// Test resendSignUpCode operation can be invoked without options
///
/// - Given: Given a configured auth plugin
/// - When:
/// - I call resendSignUpCode operation
/// - Then:
/// - I should get a valid operation object
///
func testResendSignupCodeRequestWithoutOptions() async throws {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
}
/// Test a successful resendSignUpCode call with .email as the destination of AuthCodeDeliveryDetails
///
/// - Given: Given an auth plugin with mocked service. Mocked service calls should mock a successul response
/// - When:
/// - I invoke resendSignUpCode with username
/// - Then:
/// - I should get a successful result with .email as the destination of AuthCodeDeliveryDetails
///
func testResendSignupCodeWithSuccess() async throws {
let codeDeliveryDetails = CognitoIdentityProviderClientTypes.CodeDeliveryDetailsType(attributeName: nil,
deliveryMedium: .email,
destination: nil)
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
ResendConfirmationCodeOutputResponse(codeDeliveryDetails: codeDeliveryDetails)
}
)
let authCodeDeliveryDetails = try await plugin.resendSignUpCode(for: "username", options: nil)
guard case .email = authCodeDeliveryDetails.destination else {
XCTFail("Result should be .email for the destination of AuthCodeDeliveryDetails")
return
}
}
/// Test a resendSignUpCode call with empty username
///
/// - Given: Given an auth plugin with mocked service. Mocked service calls should mock a successful response
/// - When:
/// - I invoke resendSignUpCode with username
/// - Then:
/// - I should get a failure with validation error
///
func testResendSignupCodeWithEmptyUsername() async throws {
let codeDeliveryDetails = CognitoIdentityProviderClientTypes.CodeDeliveryDetailsType(attributeName: nil,
deliveryMedium: .email,
destination: nil)
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
ResendConfirmationCodeOutputResponse(codeDeliveryDetails: codeDeliveryDetails)
}
)
do {
_ = try await plugin.resendSignUpCode(for: "", options: nil)
XCTFail("Should not succeed")
} catch {
guard case AuthError.validation = error else {
XCTFail("Should produce validation error instead of \(error)")
return
}
}
}
/// Test a resendSignUpCode call with invalid response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a invalid response
/// - When:
/// - I invoke resendSignUpCode with valid username
/// - Then:
/// - I should get an .unknown error
///
func testResendSignupCodeWithInvalidResult() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw AuthError.unknown("Unknown error", nil)
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should not succeed")
} catch {
guard case AuthError.unknown = error else {
XCTFail("Should produce an unknown error")
return
}
}
}
// MARK: Service error handling test
/// Test a resendSignUpCode call with CodeDeliveryFailureException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// CodeDeliveryFailureException response
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .codeDelivery as underlyingError
///
func testResendSignupCodeWithCodeDeliveryFailureException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.codeDeliveryFailureException(CodeDeliveryFailureException(message: "Code delivery failure"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .codeDelivery = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be codedelivery \(error)")
return
}
}
}
/// Test a resendSignUpCode call with InternalErrorException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a InternalErrorException response
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get an .unknown error
///
func testResendSignupCodeWithInternalErrorException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.internalErrorException(InternalErrorException(message: "internal error"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.unknown = error else {
XCTFail("Should produce an unknown error instead of \(error)")
return
}
}
}
/// Test a resendSignUpCode call with InvalidEmailRoleAccessPolicy response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// InvalidEmailRoleAccessPolicyException response
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .emailRole as underlyingError
///
func testResendSignupCodeWithInvalidEmailRoleAccessPolicyException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.invalidEmailRoleAccessPolicyException(InvalidEmailRoleAccessPolicyException(message: "Invalid email role access policy"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .emailRole = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be sms role \(error)")
return
}
}
}
/// Test a resendSignUpCode call with InvalidSmsRoleAccessPolicy response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// InvalidSmsRoleAccessPolicyException response
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .smsRole as underlyingError
///
func testResendSignupCodeWithinvalidSmsRoleAccessPolicyException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.invalidSmsRoleAccessPolicyException(InvalidSmsRoleAccessPolicyException(message: "Invalid sms role access policy"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .smsRole = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be sms role \(error)")
return
}
}
}
/// Test a resendSignUpCode call with InvalidSmsRoleTrustRelationship response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// InvalidSmsRoleTrustRelationshipException response
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .smsRole as underlyingError
///
func testResendSignupCodeWithInvalidSmsRoleTrustRelationshipException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.invalidSmsRoleTrustRelationshipException(InvalidSmsRoleTrustRelationshipException(message: "Invalid sms role trust relationship"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .smsRole = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be sms role \(error)")
return
}
}
}
/// Test a resendSignUpCode call with InvalidLambdaResponseException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// InvalidLambdaResponseException response
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .lambda as underlyingError
///
func testResendSignupCodeWithInvalidLambdaResponseException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.invalidLambdaResponseException(InvalidLambdaResponseException(message: "Invalid lambda response"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .lambda = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be lambda \(error)")
return
}
}
}
/// Test a resendSignUpCode call with InvalidParameterException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// InvalidParameterException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .invalidParameter as underlyingError
///
func testResendSignupCodeWithInvalidParameterException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.invalidParameterException(InvalidParameterException(message: "invalid parameter"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .invalidParameter = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be invalidParameter \(error)")
return
}
}
}
/// Test a resendSignUpCode call with LimitExceededException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// LimitExceededException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .limitExceeded error
///
func testResendSignupCodeWithLimitExceededException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.limitExceededException(LimitExceededException(message: "limit exceeded"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .limitExceeded = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be limitExceeded \(error)")
return
}
}
}
/// Test a resendSignUpCode call with NotAuthorizedException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// NotAuthorizedException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .notAuthorized error
///
func testResendSignupCodeWithNotAuthorizedException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.notAuthorizedException(NotAuthorizedException(message: "not authorized"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.notAuthorized = error else {
XCTFail("Should produce notAuthorized error instead of \(error)")
return
}
}
}
/// Test a resendSignUpCode call with ResourceNotFoundException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// ResourceNotFoundException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .resourceNotFound as underlyingError
///
func testResendSignupCodeWithResourceNotFoundException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.resourceNotFoundException(ResourceNotFoundException(message: "resource not found"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .resourceNotFound = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be resourceNotFound \(error)")
return
}
}
}
/// Test a resendSignUpCode call with TooManyRequestsException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// TooManyRequestsException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .requestLimitExceeded as underlyingError
///
func testResendSignupCodeWithTooManyRequestsException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.tooManyRequestsException(TooManyRequestsException(message: "too many requests"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .requestLimitExceeded = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be requestLimitExceeded \(error)")
return
}
}
}
/// Test a resendSignUpCode call with UnexpectedLambdaException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// UnexpectedLambdaException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .lambda as underlyingError
///
func testResendSignupCodeWithUnexpectedLambdaException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.unexpectedLambdaException(UnexpectedLambdaException(message: "unexpected lambda"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .lambda = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be lambda \(error)")
return
}
}
}
/// Test a resendSignUpCode call with UserLambdaValidationException response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// UserLambdaValidationException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .service error with .lambda as underlyingError
///
func testResendSignupCodeWithUserLambdaValidationException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.userLambdaValidationException(UserLambdaValidationException(message: "user lambda validation exception"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .lambda = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be lambda \(error)")
return
}
}
}
/// Test a resendSignUpCode call with UserNotFound response from service
///
/// - Given: Given an auth plugin with mocked service. Mocked service should mock a
/// UserNotFoundException response
///
/// - When:
/// - I invoke resendSignUpCode with a valid username
/// - Then:
/// - I should get a .userNotFound error
///
func testResendSignupCodeUpWithUserNotFoundException() async throws {
mockIdentityProvider = MockIdentityProvider(
mockResendConfirmationCodeOutputResponse: { _ in
throw ResendConfirmationCodeOutputError.userNotFoundException(UserNotFoundException(message: "user not found"))
}
)
do {
_ = try await plugin.resendSignUpCode(for: "username", options: nil)
XCTFail("Should return an error if the result from service is invalid")
} catch {
guard case AuthError.service(_, _, let underlyingError) = error else {
XCTFail("Should produce service error instead of \(error)")
return
}
guard case .userNotFound = (underlyingError as? AWSCognitoAuthError) else {
XCTFail("Underlying error should be userNotFound \(error)")
return
}
}
}
}