blob: c4e1ac1d059d389b0c75022d22640c2f626ba611 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <XCTest/XCTest.h>
#import "Stubs.h"
@import in_app_purchase_storekit;
@interface TranslatorTest : XCTestCase
@property(strong, nonatomic) NSDictionary *periodMap;
@property(strong, nonatomic) NSDictionary *discountMap;
@property(strong, nonatomic) NSMutableDictionary *productMap;
@property(strong, nonatomic) NSDictionary *productResponseMap;
@property(strong, nonatomic) NSDictionary *paymentMap;
@property(copy, nonatomic) NSDictionary *paymentDiscountMap;
@property(strong, nonatomic) NSDictionary *transactionMap;
@property(strong, nonatomic) NSDictionary *errorMap;
@property(strong, nonatomic) NSDictionary *localeMap;
@property(strong, nonatomic) NSDictionary *storefrontMap;
@property(strong, nonatomic) NSDictionary *storefrontAndPaymentTransactionMap;
@end
@implementation TranslatorTest
- (void)setUp {
self.periodMap = @{@"numberOfUnits" : @(0), @"unit" : @(0)};
self.discountMap = @{
@"price" : @"1",
@"priceLocale" : [FIAObjectTranslator getMapFromNSLocale:NSLocale.systemLocale],
@"numberOfPeriods" : @1,
@"subscriptionPeriod" : self.periodMap,
@"paymentMode" : @1
};
self.productMap = [[NSMutableDictionary alloc] initWithDictionary:@{
@"price" : @"1",
@"priceLocale" : [FIAObjectTranslator getMapFromNSLocale:NSLocale.systemLocale],
@"productIdentifier" : @"123",
@"localizedTitle" : @"title",
@"localizedDescription" : @"des",
}];
if (@available(iOS 11.2, *)) {
self.productMap[@"subscriptionPeriod"] = self.periodMap;
self.productMap[@"introductoryPrice"] = self.discountMap;
}
if (@available(iOS 12.2, *)) {
self.productMap[@"discounts"] = @[ self.discountMap ];
}
if (@available(iOS 12.0, *)) {
self.productMap[@"subscriptionGroupIdentifier"] = @"com.group";
}
self.productResponseMap =
@{@"products" : @[ self.productMap ], @"invalidProductIdentifiers" : @[]};
self.paymentMap = @{
@"productIdentifier" : @"123",
@"requestData" : @"abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
@"quantity" : @(2),
@"applicationUsername" : @"app user name",
@"simulatesAskToBuyInSandbox" : @(NO)
};
self.paymentDiscountMap = @{
@"identifier" : @"payment_discount_identifier",
@"keyIdentifier" : @"payment_discount_key_identifier",
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
@"signature" : @"this is a encrypted signature",
@"timestamp" : @([NSDate date].timeIntervalSince1970),
};
NSDictionary *originalTransactionMap = @{
@"transactionIdentifier" : @"567",
@"transactionState" : @(SKPaymentTransactionStatePurchasing),
@"payment" : [NSNull null],
@"error" : [FIAObjectTranslator getMapFromNSError:[NSError errorWithDomain:@"test_stub"
code:123
userInfo:@{}]],
@"transactionTimeStamp" : @([NSDate date].timeIntervalSince1970),
@"originalTransaction" : [NSNull null],
};
self.transactionMap = @{
@"transactionIdentifier" : @"567",
@"transactionState" : @(SKPaymentTransactionStatePurchasing),
@"payment" : [NSNull null],
@"error" : [FIAObjectTranslator getMapFromNSError:[NSError errorWithDomain:@"test_stub"
code:123
userInfo:@{}]],
@"transactionTimeStamp" : @([NSDate date].timeIntervalSince1970),
@"originalTransaction" : originalTransactionMap,
};
self.errorMap = @{
@"code" : @(123),
@"domain" : @"test_domain",
@"userInfo" : @{
@"key" : @"value",
}
};
self.storefrontMap = @{
@"countryCode" : @"USA",
@"identifier" : @"unique_identifier",
};
self.storefrontAndPaymentTransactionMap = @{
@"storefront" : self.storefrontMap,
@"transaction" : self.transactionMap,
};
}
- (void)testSKProductSubscriptionPeriodStubToMap {
if (@available(iOS 11.2, *)) {
SKProductSubscriptionPeriodStub *period =
[[SKProductSubscriptionPeriodStub alloc] initWithMap:self.periodMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKProductSubscriptionPeriod:period];
XCTAssertEqualObjects(map, self.periodMap);
}
}
- (void)testSKProductDiscountStubToMap {
if (@available(iOS 11.2, *)) {
SKProductDiscountStub *discount = [[SKProductDiscountStub alloc] initWithMap:self.discountMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKProductDiscount:discount];
XCTAssertEqualObjects(map, self.discountMap);
}
}
- (void)testProductToMap {
SKProductStub *product = [[SKProductStub alloc] initWithMap:self.productMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKProduct:product];
XCTAssertEqualObjects(map, self.productMap);
}
- (void)testProductResponseToMap {
SKProductsResponseStub *response =
[[SKProductsResponseStub alloc] initWithMap:self.productResponseMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKProductsResponse:response];
XCTAssertEqualObjects(map, self.productResponseMap);
}
- (void)testPaymentToMap {
SKMutablePayment *payment = [FIAObjectTranslator getSKMutablePaymentFromMap:self.paymentMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKPayment:payment];
XCTAssertEqualObjects(map, self.paymentMap);
}
- (void)testPaymentTransactionToMap {
// payment is not KVC, cannot test payment field.
SKPaymentTransactionStub *paymentTransaction =
[[SKPaymentTransactionStub alloc] initWithMap:self.transactionMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKPaymentTransaction:paymentTransaction];
XCTAssertEqualObjects(map, self.transactionMap);
}
- (void)testError {
NSErrorStub *error = [[NSErrorStub alloc] initWithMap:self.errorMap];
NSDictionary *map = [FIAObjectTranslator getMapFromNSError:error];
XCTAssertEqualObjects(map, self.errorMap);
}
- (void)testErrorWithNSNumberAsUserInfo {
NSError *error = [NSError errorWithDomain:SKErrorDomain code:3 userInfo:@{@"key" : @42}];
NSDictionary *expectedMap =
@{@"domain" : SKErrorDomain, @"code" : @3, @"userInfo" : @{@"key" : @42}};
NSDictionary *map = [FIAObjectTranslator getMapFromNSError:error];
XCTAssertEqualObjects(expectedMap, map);
}
- (void)testErrorWithMultipleUnderlyingErrors {
NSError *underlyingErrorOne = [NSError errorWithDomain:SKErrorDomain code:2 userInfo:nil];
NSError *underlyingErrorTwo = [NSError errorWithDomain:SKErrorDomain code:1 userInfo:nil];
NSError *mainError = [NSError
errorWithDomain:SKErrorDomain
code:3
userInfo:@{@"underlyingErrors" : @[ underlyingErrorOne, underlyingErrorTwo ]}];
NSDictionary *expectedMap = @{
@"domain" : SKErrorDomain,
@"code" : @3,
@"userInfo" : @{
@"underlyingErrors" : @[
@{@"domain" : SKErrorDomain, @"code" : @2, @"userInfo" : @{}},
@{@"domain" : SKErrorDomain, @"code" : @1, @"userInfo" : @{}}
]
}
};
NSDictionary *map = [FIAObjectTranslator getMapFromNSError:mainError];
XCTAssertEqualObjects(expectedMap, map);
}
- (void)testErrorWithUnsupportedUserInfo {
NSError *error = [NSError errorWithDomain:SKErrorDomain
code:3
userInfo:@{@"user_info" : [[NSObject alloc] init]}];
NSDictionary *expectedMap = @{
@"domain" : SKErrorDomain,
@"code" : @3,
@"userInfo" : @{
@"user_info" : [NSString
stringWithFormat:
@"Unable to encode native userInfo object of type %@ to map. Please submit an "
@"issue at https://github.com/flutter/flutter/issues/new with the title "
@"\"[in_app_purchase_storekit] Unable to encode userInfo of type %@\" and add "
@"reproduction steps and the error details in the description field.",
[NSObject class], [NSObject class]]
}
};
NSDictionary *map = [FIAObjectTranslator getMapFromNSError:error];
XCTAssertEqualObjects(expectedMap, map);
}
- (void)testLocaleToMap {
if (@available(iOS 10.0, *)) {
NSLocale *system = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSDictionary *map = [FIAObjectTranslator getMapFromNSLocale:system];
XCTAssertEqualObjects(map[@"currencySymbol"], system.currencySymbol);
XCTAssertEqualObjects(map[@"countryCode"], system.countryCode);
}
}
- (void)testSKStorefrontToMap {
if (@available(iOS 13.0, *)) {
SKStorefront *storefront = [[SKStorefrontStub alloc] initWithMap:self.storefrontMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKStorefront:storefront];
XCTAssertEqualObjects(map, self.storefrontMap);
}
}
- (void)testSKStorefrontAndSKPaymentTransactionToMap {
if (@available(iOS 13.0, *)) {
SKStorefront *storefront = [[SKStorefrontStub alloc] initWithMap:self.storefrontMap];
SKPaymentTransaction *transaction =
[[SKPaymentTransactionStub alloc] initWithMap:self.transactionMap];
NSDictionary *map = [FIAObjectTranslator getMapFromSKStorefront:storefront
andSKPaymentTransaction:transaction];
XCTAssertEqualObjects(map, self.storefrontAndPaymentTransactionMap);
}
}
- (void)testSKPaymentDiscountFromMap {
if (@available(iOS 12.2, *)) {
NSString *error = nil;
SKPaymentDiscount *paymentDiscount =
[FIAObjectTranslator getSKPaymentDiscountFromMap:self.paymentDiscountMap withError:&error];
XCTAssertEqual(paymentDiscount.identifier, self.paymentDiscountMap[@"identifier"]);
XCTAssertEqual(paymentDiscount.keyIdentifier, self.paymentDiscountMap[@"keyIdentifier"]);
XCTAssertEqualObjects(paymentDiscount.nonce,
[[NSUUID alloc] initWithUUIDString:self.paymentDiscountMap[@"nonce"]]);
XCTAssertEqual(paymentDiscount.signature, self.paymentDiscountMap[@"signature"]);
XCTAssertEqual(paymentDiscount.timestamp, self.paymentDiscountMap[@"timestamp"]);
}
}
- (void)testSKPaymentDiscountFromMapMissingIdentifier {
if (@available(iOS 12.2, *)) {
NSArray *invalidValues = @[ [NSNull null], @(1), @"" ];
for (id value in invalidValues) {
NSDictionary *discountMap = @{
@"identifier" : value,
@"keyIdentifier" : @"payment_discount_key_identifier",
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
@"signature" : @"this is a encrypted signature",
@"timestamp" : @([NSDate date].timeIntervalSince1970),
};
NSString *error = nil;
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
XCTAssertNotNil(error);
XCTAssertEqualObjects(
error, @"When specifying a payment discount the 'identifier' field is mandatory.");
}
}
}
- (void)testSKPaymentDiscountFromMapMissingKeyIdentifier {
if (@available(iOS 12.2, *)) {
NSArray *invalidValues = @[ [NSNull null], @(1), @"" ];
for (id value in invalidValues) {
NSDictionary *discountMap = @{
@"identifier" : @"payment_discount_identifier",
@"keyIdentifier" : value,
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
@"signature" : @"this is a encrypted signature",
@"timestamp" : @([NSDate date].timeIntervalSince1970),
};
NSString *error = nil;
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
XCTAssertNotNil(error);
XCTAssertEqualObjects(
error, @"When specifying a payment discount the 'keyIdentifier' field is mandatory.");
}
}
}
- (void)testSKPaymentDiscountFromMapMissingNonce {
if (@available(iOS 12.2, *)) {
NSArray *invalidValues = @[ [NSNull null], @(1), @"" ];
for (id value in invalidValues) {
NSDictionary *discountMap = @{
@"identifier" : @"payment_discount_identifier",
@"keyIdentifier" : @"payment_discount_key_identifier",
@"nonce" : value,
@"signature" : @"this is a encrypted signature",
@"timestamp" : @([NSDate date].timeIntervalSince1970),
};
NSString *error = nil;
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
XCTAssertNotNil(error);
XCTAssertEqualObjects(error,
@"When specifying a payment discount the 'nonce' field is mandatory.");
}
}
}
- (void)testSKPaymentDiscountFromMapMissingSignature {
if (@available(iOS 12.2, *)) {
NSArray *invalidValues = @[ [NSNull null], @(1), @"" ];
for (id value in invalidValues) {
NSDictionary *discountMap = @{
@"identifier" : @"payment_discount_identifier",
@"keyIdentifier" : @"payment_discount_key_identifier",
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
@"signature" : value,
@"timestamp" : @([NSDate date].timeIntervalSince1970),
};
NSString *error = nil;
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
XCTAssertNotNil(error);
XCTAssertEqualObjects(
error, @"When specifying a payment discount the 'signature' field is mandatory.");
}
}
}
- (void)testSKPaymentDiscountFromMapMissingTimestamp {
if (@available(iOS 12.2, *)) {
NSArray *invalidValues = @[ [NSNull null], @"", @(-1) ];
for (id value in invalidValues) {
NSDictionary *discountMap = @{
@"identifier" : @"payment_discount_identifier",
@"keyIdentifier" : @"payment_discount_key_identifier",
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
@"signature" : @"this is a encrypted signature",
@"timestamp" : value,
};
NSString *error = nil;
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
XCTAssertNotNil(error);
XCTAssertEqualObjects(
error, @"When specifying a payment discount the 'timestamp' field is mandatory.");
}
}
}
@end