238 lines
9.5 KiB
Swift
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"
|
|
}
|