element-ios/RiotTests/Modules/Authentication/RegistrationTests.swift

183 lines
8.5 KiB
Swift

//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//
import XCTest
@testable import Element
class RegistrationTests: XCTestCase {
/// Makes an authentication session that mimics the matrix.org flow.
func makeSession() -> MXAuthenticationSession {
let flow = MXLoginFlow()
flow.stages = [kMXLoginFlowTypeRecaptcha, kMXLoginFlowTypeTerms, kMXLoginFlowTypeEmailIdentity]
let session = MXAuthenticationSession()
session.flows = [flow]
session.params = [:]
return session
}
/// Makes an authentication session that has two flows.
func makeSessionWithTwoFlows() -> MXAuthenticationSession {
let flow1 = MXLoginFlow()
flow1.stages = [kMXLoginFlowTypeMSISDN, kMXLoginFlowTypeTerms, kMXLoginFlowTypeRecaptcha]
let flow2 = MXLoginFlow()
flow2.stages = [kMXLoginFlowTypeEmailIdentity, kMXLoginFlowTypeTerms, kMXLoginFlowTypeRecaptcha]
let session = MXAuthenticationSession()
session.flows = [flow1, flow2]
session.params = [:]
return session
}
func testRegistrationResultForNewSession() {
// Given a fresh session.
let session = makeSession()
// Then the result should have no completed stages.
let flowResult = session.flowResult
XCTAssertEqual(flowResult.completedStages.count, 0,
"There should be no completed stages for a new session.")
XCTAssertEqual(flowResult.missingStages.count, 3,
"The result should have 3 missing stages.")
XCTAssertEqual(flowResult.nextUncompletedStage, .reCaptcha(isMandatory: true, siteKey: ""),
"The first stage should match the order in the session.")
XCTAssertEqual(flowResult.nextUncompletedStageOrdered, .email(isMandatory: true),
"The first stage when ordered should be Email for a new session.")
XCTAssertFalse(flowResult.needsFallback,
"Fallback shouldn't be needed when the stages are all supported.")
}
func testRegistrationResultAfterEmail() {
// Given a fresh session.
let session = makeSession()
// When completing the email stage.
session.completed = [kMXLoginFlowTypeEmailIdentity]
// Then the result should reflect the first stage has been completed.
let flowResult = session.flowResult
XCTAssertEqual(flowResult.completedStages.count, 1,
"The result should have 1 completed stage.")
XCTAssertEqual(flowResult.missingStages.count, 2,
"The result should have 2 missing stages.")
XCTAssertEqual(flowResult.nextUncompletedStage, .reCaptcha(isMandatory: true, siteKey: ""),
"The next stage should be the ReCaptcha stage.")
XCTAssertEqual(flowResult.nextUncompletedStageOrdered, .terms(isMandatory: true, terms: MXLoginTerms(fromJSON: [:])),
"The next stage when ordered should be the Terms stage.")
}
func testRegistrationResultAfterEmailAndTerms() {
// Given a fresh session.
let session = makeSession()
// When completing the email and terms stages.
session.completed = [kMXLoginFlowTypeEmailIdentity, kMXLoginFlowTypeTerms]
// Then the result should reflect the first 2 stages have been completed.
let flowResult = session.flowResult
XCTAssertEqual(flowResult.completedStages.count, 2,
"The result should have 2 completed stages.")
XCTAssertEqual(flowResult.missingStages.count, 1,
"The result should have 1 missing stage.")
XCTAssertEqual(flowResult.nextUncompletedStage, .reCaptcha(isMandatory: true, siteKey: ""),
"The next stage should be the ReCaptcha stage.")
XCTAssertEqual(flowResult.nextUncompletedStageOrdered, .reCaptcha(isMandatory: true, siteKey: ""),
"The next stage when ordered should be the ReCaptcha stage.")
}
func testRegistrationResultAfterAllStages() {
// Given a fresh session.
let session = makeSession()
// When completing all of the stages.
session.completed = [kMXLoginFlowTypeEmailIdentity, kMXLoginFlowTypeTerms, kMXLoginFlowTypeRecaptcha]
// Then the result shouldn't have any missing stages.
let flowResult = session.flowResult
XCTAssertEqual(flowResult.completedStages.count, 3,
"The result should have all completed stages.")
XCTAssertEqual(flowResult.missingStages.count, 0,
"The result should have no missing stages.")
XCTAssertNil(flowResult.nextUncompletedStage,
"There shouldn't be any more stages to complete.")
XCTAssertNil(flowResult.nextUncompletedStageOrdered,
"There shouldn't be any more stages to complete.")
}
func testRegistrationResultCustomStage() {
// Given a session that contains a single flow with a custom stage.
let session = makeSession()
session.flows.first?.stages.append("test.flow")
// Then the result should indicate that fallback authentication should be used.
let flowResult = session.flowResult
XCTAssertTrue(flowResult.needsFallback, "Fallback should be required when a custom stage is present.")
}
func testRegistrationResultTwoFlows() {
// Given a session with two flows.
let session = makeSessionWithTwoFlows()
// Then the result should know the mandatory/optional stages and start with the mandatory stages unless ordered
let flowResult = session.flowResult
XCTAssertFalse(flowResult.needsFallback,
"Fallback shouldn't be needed when the stages are all supported.")
XCTAssertEqual(flowResult.nextUncompletedStage, .terms(isMandatory: true, terms: MXLoginTerms(fromJSON: [:])),
"The first stage should be the Terms stage.")
XCTAssertEqual(flowResult.nextUncompletedStageOrdered, .email(isMandatory: false),
"The first stage when ordered should be the Email stage.")
flowResult.missingStages.forEach { stage in
switch stage {
case .email(let isMandatory):
XCTAssertFalse(isMandatory, "The Email stage should be optional.")
case .msisdn(let isMandatory):
XCTAssertFalse(isMandatory, "The MSISDN stage should be optional.")
case .terms(let isMandatory, _):
XCTAssertTrue(isMandatory, "The Terms stage should be mandatory.")
case .reCaptcha(let isMandatory, _):
XCTAssertTrue(isMandatory, "The ReCaptcha stage should be mandatory.")
default:
XCTFail("There shouldn't be any other types of stage in the result.")
}
}
}
func testRegistrationResultTwoFlowsAfterMandatoryStages() {
// Given a session with two flows.
let session = makeSessionWithTwoFlows()
// When completing the terms and recaptcha stages.
session.completed = [kMXLoginFlowTypeTerms, kMXLoginFlowTypeRecaptcha]
// Then the result should have the optional stages remaining.
let flowResult = session.flowResult
XCTAssertEqual(flowResult.completedStages.count, 2,
"The result should have 2 completed stages.")
XCTAssertEqual(flowResult.missingStages.count, 2,
"The result should have 2 missing stage.")
XCTAssertEqual(flowResult.nextUncompletedStage, .msisdn(isMandatory: false),
"The next stage should be the MSISDN stage.")
XCTAssertEqual(flowResult.nextUncompletedStageOrdered, .email(isMandatory: false),
"The next stage when ordered should be the Email stage.")
}
func testRegistrationResultTwoFlowsCustomStage() {
// Given a session with a custom stage in a second flow.
let session = makeSession()
let flow = MXLoginFlow()
flow.stages = ["test.flow"]
session.flows.append(flow)
// Then the session shouldn't need fallback.
let flowResult = session.flowResult
XCTAssertFalse(flowResult.needsFallback, "Fallback shouldn't be required when a custom stage is optional.")
}
}