DailyView/Carthage/Checkouts/facebook-ios-sdk/FBSDKShareKit/FBSDKShareKitTests/Content/AppInviteContentTests.swift
2025-12-30 16:40:31 +08:00

238 lines
9.5 KiB
Swift

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*/
@testable import FBSDKShareKit
import FBSDKCoreKit
import TestTools
import XCTest
final class AppInviteContentTests: XCTestCase {
// swiftlint:disable implicitly_unwrapped_optional force_unwrapping
var content: AppInviteContent!
let appLinkURL = URL(string: "https://fb.me/1595011414049078")!
let appInvitePreviewImageURL = URL(string: "https://fbstatic-a.akamaihd.net/rsrc.php/v2/y6/r/YQEGe6GxI_M.png")!
var validator: TestShareUtility.Type!
var errorFactory: TestErrorFactory!
// swiftlint:enable implicitly_unwrapped_optional force_unwrapping
override func setUp() {
super.setUp()
validator = TestShareUtility.self
validator.reset()
errorFactory = TestErrorFactory()
AppInviteContent.setDependencies(
.init(
validator: validator,
errorFactory: errorFactory
)
)
content = AppInviteContent(appLinkURL: appLinkURL)
content.appInvitePreviewImageURL = appInvitePreviewImageURL
}
override func tearDown() {
AppInviteContent.resetDependencies()
validator.reset()
validator = nil
errorFactory = nil
content = nil
super.tearDown()
}
func testDefaultDependencies() throws {
AppInviteContent.resetDependencies()
let dependencies = try AppInviteContent.getDependencies()
XCTAssertTrue(dependencies.validator is _ShareUtility.Type, .usesShareUtilityByDefault)
XCTAssertTrue(dependencies.errorFactory is _ErrorFactory, .usesErrorFactoryByDefault)
}
func testCustomDependencies() throws {
let dependencies = try AppInviteContent.getDependencies()
XCTAssertTrue(dependencies.validator is TestShareUtility.Type, .usesCustomShareValidator)
XCTAssertIdentical(dependencies.errorFactory as AnyObject, errorFactory, .usesCustomErrorFactory)
}
func testProperties() {
XCTAssertEqual(content.appLinkURL, appLinkURL, .hasAppLinkURL)
XCTAssertEqual(content.appInvitePreviewImageURL, appInvitePreviewImageURL, .hasAppInvitePreviewImageURL)
}
func testValidationWithValidContent() throws {
XCTAssertNoThrow(try content.validate(options: []), .passesValidationWithValidContent)
}
func testValidationWithNilPreviewImageURL() {
content = AppInviteContent(appLinkURL: appLinkURL)
XCTAssertNoThrow(try content.validate(options: []), .passesValidationWithoutPreviewImageURL)
}
func testValidationWithNilPromotionTextNilPromotionCode() {
content = AppInviteContent(appLinkURL: appLinkURL)
XCTAssertNoThrow(try content.validate(options: []), .passesValidationWithoutPromotionTextAndPromotionCode)
}
func testValidationWithValidPromotionCodeNilPromotionText() {
content.promotionCode = "XSKSK"
XCTAssertThrowsError(
try content.validate(options: []),
.failsValidationWithPromotionCodeOnly
) { error in
guard let sdkError = error as? TestSDKError else {
return XCTFail(.failsValidationWithPromotionCodeOnly)
}
XCTAssertEqual(sdkError.type, .invalidArgument, .failsValidationWithPromotionCodeOnly)
XCTAssertEqual(sdkError.name, "promotionText", .failsValidationWithPromotionCodeOnly)
XCTAssertEqual(sdkError.value as? String, content.promotionText, .failsValidationWithPromotionCodeOnly)
XCTAssertEqual(
sdkError.message,
"Invalid value for promotionText; promotionText has to be between 1 and 80 characters long.",
.failsValidationWithPromotionCodeOnly
)
XCTAssertNil(sdkError.underlyingError, .failsValidationWithPromotionCodeOnly)
}
}
func testValidationWithValidPromotionTextNilPromotionCode() {
content.promotionText = "Some Promo Text"
XCTAssertNoThrow(try content.validate(options: []), .failsValidationWithPromotionTextOnly)
}
func testValidationWithBadPromotionTextLength() {
content.promotionText = String(repeating: "_Invalid_promotionText", count: 30)
XCTAssertThrowsError(
try content.validate(options: []),
.failsValidationWithShortPromotionText
) { error in
guard let sdkError = error as? TestSDKError else {
return XCTFail(.failsValidationWithShortPromotionText)
}
XCTAssertEqual(sdkError.type, .invalidArgument, .failsValidationWithShortPromotionText)
XCTAssertEqual(sdkError.name, "promotionText", .failsValidationWithShortPromotionText)
XCTAssertEqual(sdkError.value as? String, content.promotionText, .failsValidationWithShortPromotionText)
XCTAssertEqual(
sdkError.message,
"Invalid value for promotionText; promotionText has to be between 1 and 80 characters long.",
.failsValidationWithShortPromotionText
)
XCTAssertNil(sdkError.underlyingError, .failsValidationWithShortPromotionText)
}
}
func testValidationWithBadPromotionTextContent() {
content.promotionText = "_Invalid_promotionText"
XCTAssertThrowsError(
try content.validate(options: []),
.failsValidationWithBadPromotionTextContent
) { error in
guard let sdkError = error as? TestSDKError else {
return XCTFail(.failsValidationWithBadPromotionTextContent)
}
XCTAssertEqual(sdkError.type, .invalidArgument, .failsValidationWithBadPromotionTextContent)
XCTAssertEqual(sdkError.name, "promotionText", .failsValidationWithBadPromotionTextContent)
XCTAssertEqual(sdkError.value as? String, content.promotionText, .failsValidationWithBadPromotionTextContent)
XCTAssertEqual(
sdkError.message,
"Invalid value for promotionText; promotionText can contain only alphanumeric characters and spaces.",
.failsValidationWithBadPromotionTextContent
)
XCTAssertNil(sdkError.underlyingError, .failsValidationWithBadPromotionTextContent)
}
}
func testValidationWithBadPromotionCodeLength() {
content.promotionText = "Some promo text"
content.promotionCode = "_invalid promo_code"
XCTAssertThrowsError(
try content.validate(options: []),
.failsValidationWithShortPromotionCode
) { error in
guard let sdkError = error as? TestSDKError else {
return XCTFail(.failsValidationWithShortPromotionCode)
}
XCTAssertEqual(sdkError.type, .invalidArgument, .failsValidationWithShortPromotionCode)
XCTAssertEqual(sdkError.name, "promotionCode", .failsValidationWithShortPromotionCode)
XCTAssertEqual(sdkError.value as? String, content.promotionCode, .failsValidationWithShortPromotionCode)
XCTAssertEqual(
sdkError.message,
"""
Invalid value for promotionCode; promotionCode has to be between 0 and 10 characters long \
and is required when promoCode is set.
""",
.failsValidationWithShortPromotionCode
)
XCTAssertNil(sdkError.underlyingError, .failsValidationWithShortPromotionCode)
}
}
func testValidationWithBadPromotionCodeContent() {
content.promotionText = "Some promo text"
content.promotionCode = "_invalid"
XCTAssertThrowsError(
try content.validate(options: []),
.failsValidationWithBadPromotionCode
) { error in
guard let sdkError = error as? TestSDKError else {
return XCTFail(.failsValidationWithBadPromotionCode)
}
XCTAssertEqual(sdkError.type, .invalidArgument, .failsValidationWithBadPromotionCode)
XCTAssertEqual(sdkError.name, "promotionCode", .failsValidationWithBadPromotionCode)
XCTAssertEqual(sdkError.value as? String, content.promotionCode, .failsValidationWithBadPromotionCode)
XCTAssertEqual(
sdkError.message,
"Invalid value for promotionCode; promotionCode can contain only alphanumeric characters and spaces.",
.failsValidationWithBadPromotionCode
)
XCTAssertNil(sdkError.underlyingError, .failsValidationWithBadPromotionCode)
}
}
}
// swiftformat:disable extensionaccesscontrol
// MARK: - Assumptions
fileprivate extension String {
static let usesErrorFactoryByDefault = "The default error factory dependency should be a concrete _ErrorFactory"
static let usesShareUtilityByDefault = "The default share validator dependency should be the _ShareUtility type"
static let usesCustomErrorFactory = "The error factory dependency should be configurable"
static let usesCustomShareValidator = "The share validator dependency should be configurable"
static let hasAppLinkURL = "An app invite content has an app link URL"
static let hasAppInvitePreviewImageURL = "An app invite content has an invite preview image URL"
static let passesValidationWithValidContent = "Validation should pass with valid content"
static let passesValidationWithoutPreviewImageURL = "Validation should pass without a preview image URL"
static let passesValidationWithoutPromotionTextAndPromotionCode = """
Validation should pass when missing both promotion text and promotion code
"""
static let failsValidationWithPromotionCodeOnly = "Validation should fail with only a promotion code"
static let failsValidationWithPromotionTextOnly = "Validation should fail with only promotion text"
static let failsValidationWithShortPromotionText = "Validation should fail with promotion text that is too short"
static let failsValidationWithBadPromotionTextContent = "Validation should fail with invalid promotion text content"
static let failsValidationWithShortPromotionCode = "Validation should fail with a promotion code that is too short"
static let failsValidationWithBadPromotionCode = "Validation should fail with invalid promotion code content"
}