mirror of
https://github.com/flutter/packages.git
synced 2025-07-01 15:23:25 +08:00
[in_app_purchase_storekit] convert TranslatorTests to swift (#7232)
Part of https://github.com/flutter/flutter/issues/151624
This commit is contained in:
@ -1,3 +1,7 @@
|
||||
## 0.3.17+3
|
||||
|
||||
* Converts TranslatorTests to swift.
|
||||
|
||||
## 0.3.17+2
|
||||
|
||||
* Converts FIAPPaymentQueueDeleteTests to swift.
|
||||
|
@ -118,11 +118,9 @@
|
||||
return nil;
|
||||
}
|
||||
NSMutableDictionary *map = [[NSMutableDictionary alloc] init];
|
||||
[map setObject:[locale objectForKey:NSLocaleCurrencySymbol] ?: [NSNull null]
|
||||
forKey:@"currencySymbol"];
|
||||
[map setObject:[locale objectForKey:NSLocaleCurrencyCode] ?: [NSNull null]
|
||||
forKey:@"currencyCode"];
|
||||
[map setObject:[locale objectForKey:NSLocaleCountryCode] ?: [NSNull null] forKey:@"countryCode"];
|
||||
[map setObject:locale.currencySymbol ?: [NSNull null] forKey:@"currencySymbol"];
|
||||
[map setObject:locale.currencyCode ?: [NSNull null] forKey:@"currencyCode"];
|
||||
[map setObject:locale.countryCode ?: [NSNull null] forKey:@"countryCode"];
|
||||
return map;
|
||||
}
|
||||
|
||||
@ -509,9 +507,9 @@
|
||||
[pigeonProducts addObject:[self convertProductToPigeon:product]];
|
||||
};
|
||||
|
||||
SKProductsResponseMessage *msg =
|
||||
[SKProductsResponseMessage makeWithProducts:pigeonProducts
|
||||
invalidProductIdentifiers:productsResponse.invalidProductIdentifiers];
|
||||
SKProductsResponseMessage *msg = [SKProductsResponseMessage
|
||||
makeWithProducts:pigeonProducts
|
||||
invalidProductIdentifiers:productsResponse.invalidProductIdentifiers ?: @[]];
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
F27694112C49BF6F00277144 /* FIAPPaymentQueueDeleteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F27694102C49BF6F00277144 /* FIAPPaymentQueueDeleteTests.swift */; };
|
||||
F27694172C49DBCA00277144 /* FIATransactionCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F27694162C49DBCA00277144 /* FIATransactionCacheTests.swift */; };
|
||||
F295AD3A2C1256DD0067C78A /* Stubs.m in Sources */ = {isa = PBXBuildFile; fileRef = F295AD392C1256DD0067C78A /* Stubs.m */; };
|
||||
F295AD462C1256F50067C78A /* TranslatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F295AD402C1256F50067C78A /* TranslatorTests.m */; };
|
||||
F2D5272A2C583C4A00C137C7 /* TranslatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D527292C583C4A00C137C7 /* TranslatorTests.swift */; };
|
||||
F2D5271A2C50627500C137C7 /* PaymentQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D527192C50627500C137C7 /* PaymentQueueTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
F27694162C49DBCA00277144 /* FIATransactionCacheTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FIATransactionCacheTests.swift; path = ../../shared/RunnerTests/FIATransactionCacheTests.swift; sourceTree = "<group>"; };
|
||||
F295AD362C1251300067C78A /* Stubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Stubs.h; path = ../../shared/RunnerTests/Stubs.h; sourceTree = "<group>"; };
|
||||
F295AD392C1256DD0067C78A /* Stubs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Stubs.m; path = ../../shared/RunnerTests/Stubs.m; sourceTree = "<group>"; };
|
||||
F295AD402C1256F50067C78A /* TranslatorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TranslatorTests.m; path = ../../shared/RunnerTests/TranslatorTests.m; sourceTree = "<group>"; };
|
||||
F2D527292C583C4A00C137C7 /* TranslatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TranslatorTests.swift; path = ../../shared/RunnerTests/TranslatorTests.swift; sourceTree = "<group>"; };
|
||||
F2D527192C50627500C137C7 /* PaymentQueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PaymentQueueTests.swift; path = ../../shared/RunnerTests/PaymentQueueTests.swift; sourceTree = "<group>"; };
|
||||
F6E5D5F926131C4800C68BED /* Configuration.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Configuration.storekit; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -186,12 +186,12 @@
|
||||
A59001A521E69658004A3E5E /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2D527292C583C4A00C137C7 /* TranslatorTests.swift */,
|
||||
F2D527192C50627500C137C7 /* PaymentQueueTests.swift */,
|
||||
F27694162C49DBCA00277144 /* FIATransactionCacheTests.swift */,
|
||||
F27694102C49BF6F00277144 /* FIAPPaymentQueueDeleteTests.swift */,
|
||||
F24C45E12C409D41000C6C72 /* InAppPurchasePluginTests.swift */,
|
||||
F276940A2C47268700277144 /* ProductRequestHandlerTests.swift */,
|
||||
F295AD402C1256F50067C78A /* TranslatorTests.m */,
|
||||
F295AD392C1256DD0067C78A /* Stubs.m */,
|
||||
F295AD362C1251300067C78A /* Stubs.h */,
|
||||
F22BF91B2BC9B40B00713878 /* SwiftStubs.swift */,
|
||||
@ -437,8 +437,8 @@
|
||||
F24C45E22C409D42000C6C72 /* InAppPurchasePluginTests.swift in Sources */,
|
||||
F22BF91C2BC9B40B00713878 /* SwiftStubs.swift in Sources */,
|
||||
F276940B2C47268700277144 /* ProductRequestHandlerTests.swift in Sources */,
|
||||
F295AD462C1256F50067C78A /* TranslatorTests.m in Sources */,
|
||||
F295AD3A2C1256DD0067C78A /* Stubs.m in Sources */,
|
||||
F2D5272A2C583C4A00C137C7 /* TranslatorTests.swift in Sources */,
|
||||
F27694172C49DBCA00277144 /* FIATransactionCacheTests.swift in Sources */,
|
||||
F27694112C49BF6F00277144 /* FIAPPaymentQueueDeleteTests.swift in Sources */,
|
||||
);
|
||||
|
@ -1 +0,0 @@
|
||||
../../shared/RunnerTests/TranslatorTests.m
|
@ -0,0 +1 @@
|
||||
../../shared/RunnerTests/TranslatorTests.swift
|
@ -32,9 +32,9 @@
|
||||
F27694132C49BF7B00277144 /* FIAPPaymentQueueDeleteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F27694122C49BF7B00277144 /* FIAPPaymentQueueDeleteTests.swift */; };
|
||||
F27694192C49DBE800277144 /* FIATransactionCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F27694182C49DBE800277144 /* FIATransactionCacheTests.swift */; };
|
||||
F2C3A7412BD9D33D000D35F2 /* Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2C3A7402BD9D33D000D35F2 /* Stubs.swift */; };
|
||||
F2D527262C583C1C00C137C7 /* TranslatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D527252C583C1C00C137C7 /* TranslatorTests.swift */; };
|
||||
F2D5271E2C50645600C137C7 /* PaymentQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D5271D2C50645600C137C7 /* PaymentQueueTests.swift */; };
|
||||
F79BDC1C2905FC3200E3999D /* Stubs.m in Sources */ = {isa = PBXBuildFile; fileRef = F79BDC1B2905FC3200E3999D /* Stubs.m */; };
|
||||
F79BDC1E2905FC3900E3999D /* TranslatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F79BDC1D2905FC3900E3999D /* TranslatorTests.m */; };
|
||||
F8270DE1AEF80A8CF2C45688 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 045C0F7D19875EDA98DF0B7F /* Pods_RunnerTests.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -97,11 +97,11 @@
|
||||
F27694182C49DBE800277144 /* FIATransactionCacheTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FIATransactionCacheTests.swift; path = ../../shared/RunnerTests/FIATransactionCacheTests.swift; sourceTree = "<group>"; };
|
||||
F2C3A73F2BD9D33D000D35F2 /* RunnerTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RunnerTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
F2C3A7402BD9D33D000D35F2 /* Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = "<group>"; };
|
||||
F2D527252C583C1C00C137C7 /* TranslatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TranslatorTests.swift; path = ../../shared/RunnerTests/TranslatorTests.swift; sourceTree = "<group>"; };
|
||||
F2D5271D2C50645600C137C7 /* PaymentQueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PaymentQueueTests.swift; path = ../../shared/RunnerTests/PaymentQueueTests.swift; sourceTree = "<group>"; };
|
||||
F700DD0228E652A10004836B /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F79BDC152905FC0500E3999D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../../shared/RunnerTests/Info.plist; sourceTree = "<group>"; };
|
||||
F79BDC1B2905FC3200E3999D /* Stubs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Stubs.m; path = ../../shared/RunnerTests/Stubs.m; sourceTree = "<group>"; };
|
||||
F79BDC1D2905FC3900E3999D /* TranslatorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TranslatorTests.m; path = ../../shared/RunnerTests/TranslatorTests.m; sourceTree = "<group>"; };
|
||||
F79BDC1F2906023C00E3999D /* Stubs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Stubs.h; path = ../../shared/RunnerTests/Stubs.h; sourceTree = "<group>"; };
|
||||
F8E47120B1A50B8A1C480FDB /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -217,6 +217,7 @@
|
||||
F700DD0328E652A10004836B /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2D527252C583C1C00C137C7 /* TranslatorTests.swift */,
|
||||
F2D5271D2C50645600C137C7 /* PaymentQueueTests.swift */,
|
||||
F27694182C49DBE800277144 /* FIATransactionCacheTests.swift */,
|
||||
F27694122C49BF7B00277144 /* FIAPPaymentQueueDeleteTests.swift */,
|
||||
@ -225,7 +226,6 @@
|
||||
F79BDC1F2906023C00E3999D /* Stubs.h */,
|
||||
F79BDC152905FC0500E3999D /* Info.plist */,
|
||||
F79BDC1B2905FC3200E3999D /* Stubs.m */,
|
||||
F79BDC1D2905FC3900E3999D /* TranslatorTests.m */,
|
||||
F2C3A7402BD9D33D000D35F2 /* Stubs.swift */,
|
||||
F2C3A73F2BD9D33D000D35F2 /* RunnerTests-Bridging-Header.h */,
|
||||
);
|
||||
@ -465,10 +465,10 @@
|
||||
files = (
|
||||
F2D5271E2C50645600C137C7 /* PaymentQueueTests.swift in Sources */,
|
||||
F24C45E42C409D87000C6C72 /* InAppPurchasePluginTests.swift in Sources */,
|
||||
F79BDC1E2905FC3900E3999D /* TranslatorTests.m in Sources */,
|
||||
F79BDC1C2905FC3200E3999D /* Stubs.m in Sources */,
|
||||
F27694092C4724B200277144 /* ProductRequestHandlerTests.swift in Sources */,
|
||||
F2C3A7412BD9D33D000D35F2 /* Stubs.swift in Sources */,
|
||||
F2D527262C583C1C00C137C7 /* TranslatorTests.swift in Sources */,
|
||||
F27694192C49DBE800277144 /* FIATransactionCacheTests.swift in Sources */,
|
||||
F27694132C49BF7B00277144 /* FIAPPaymentQueueDeleteTests.swift in Sources */,
|
||||
);
|
||||
|
@ -1 +0,0 @@
|
||||
../../shared/RunnerTests/TranslatorTests.m
|
@ -0,0 +1 @@
|
||||
../../shared/RunnerTests/TranslatorTests.swift
|
@ -82,7 +82,7 @@ final class InAppPurchasePluginTests: XCTestCase {
|
||||
}
|
||||
|
||||
XCTAssertEqual(unwrappedProducts.count, 1)
|
||||
XCTAssertEqual(response.invalidProductIdentifiers, nil)
|
||||
XCTAssertEqual(response.invalidProductIdentifiers, [])
|
||||
XCTAssertEqual(unwrappedProducts[0].productIdentifier, "123")
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
@ -1,518 +0,0 @@
|
||||
// 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) NSMutableDictionary *discountMap;
|
||||
@property(strong, nonatomic) NSMutableDictionary *discountMissingIdentifierMap;
|
||||
@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 = [[NSMutableDictionary alloc] initWithDictionary:@{
|
||||
@"price" : @"1",
|
||||
@"priceLocale" : [FIAObjectTranslator getMapFromNSLocale:NSLocale.systemLocale],
|
||||
@"numberOfPeriods" : @1,
|
||||
@"subscriptionPeriod" : self.periodMap,
|
||||
@"paymentMode" : @1,
|
||||
}];
|
||||
if (@available(iOS 12.2, *)) {
|
||||
self.discountMap[@"identifier"] = @"test offer id";
|
||||
self.discountMap[@"type"] = @(SKProductDiscountTypeIntroductory);
|
||||
}
|
||||
self.discountMissingIdentifierMap = [[NSMutableDictionary alloc] initWithDictionary:@{
|
||||
@"price" : @"1",
|
||||
@"priceLocale" : [FIAObjectTranslator getMapFromNSLocale:NSLocale.systemLocale],
|
||||
@"numberOfPeriods" : @1,
|
||||
@"subscriptionPeriod" : self.periodMap,
|
||||
@"paymentMode" : @1,
|
||||
@"identifier" : [NSNull null],
|
||||
@"type" : @0,
|
||||
}];
|
||||
|
||||
self.productMap = [[NSMutableDictionary alloc] initWithDictionary:@{
|
||||
@"price" : @"1",
|
||||
@"priceLocale" : [FIAObjectTranslator getMapFromNSLocale:NSLocale.systemLocale],
|
||||
@"productIdentifier" : @"123",
|
||||
@"localizedTitle" : @"title",
|
||||
@"localizedDescription" : @"des",
|
||||
}];
|
||||
self.productMap[@"subscriptionPeriod"] = self.periodMap;
|
||||
self.productMap[@"introductoryPrice"] = self.discountMap;
|
||||
if (@available(iOS 12.2, *)) {
|
||||
self.productMap[@"discounts"] = @[ self.discountMap ];
|
||||
}
|
||||
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 {
|
||||
SKProductSubscriptionPeriodStub *period =
|
||||
[[SKProductSubscriptionPeriodStub alloc] initWithMap:self.periodMap];
|
||||
NSDictionary *map = [FIAObjectTranslator getMapFromSKProductSubscriptionPeriod:period];
|
||||
XCTAssertEqualObjects(map, self.periodMap);
|
||||
}
|
||||
|
||||
- (void)testSKProductDiscountStubToMap {
|
||||
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)testErrorWithNestedUnderlyingError {
|
||||
NSError *underlyingError = [NSError errorWithDomain:SKErrorDomain code:2 userInfo:nil];
|
||||
NSError *mainError =
|
||||
[NSError errorWithDomain:SKErrorDomain
|
||||
code:3
|
||||
userInfo:@{@"nesting" : @{@"underlyingError" : underlyingError}}];
|
||||
NSDictionary *expectedMap = @{
|
||||
@"domain" : SKErrorDomain,
|
||||
@"code" : @3,
|
||||
@"userInfo" : @{
|
||||
@"nesting" : @{
|
||||
@"underlyingError" : @{@"domain" : SKErrorDomain, @"code" : @2, @"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 {
|
||||
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)testGetMapFromSKProductDiscountMissingIdentifier {
|
||||
if (@available(iOS 12.2, *)) {
|
||||
SKProductDiscountStub *discount =
|
||||
[[SKProductDiscountStub alloc] initWithMap:self.discountMissingIdentifierMap];
|
||||
NSDictionary *map = [FIAObjectTranslator getMapFromSKProductDiscount:discount];
|
||||
XCTAssertEqualObjects(map, self.discountMissingIdentifierMap);
|
||||
}
|
||||
}
|
||||
|
||||
- (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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSKPaymentDiscountFromMapOverflowingTimestamp {
|
||||
if (@available(iOS 12.2, *)) {
|
||||
NSDictionary *discountMap = @{
|
||||
@"identifier" : @"payment_discount_identifier",
|
||||
@"keyIdentifier" : @"payment_discount_key_identifier",
|
||||
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
@"signature" : @"this is a encrypted signature",
|
||||
@"timestamp" : @1665044583595, // timestamp 2022 Oct
|
||||
};
|
||||
NSString *error = nil;
|
||||
SKPaymentDiscount *paymentDiscount =
|
||||
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(paymentDiscount);
|
||||
XCTAssertEqual(paymentDiscount.identifier, discountMap[@"identifier"]);
|
||||
XCTAssertEqual(paymentDiscount.keyIdentifier, discountMap[@"keyIdentifier"]);
|
||||
XCTAssertEqualObjects(paymentDiscount.nonce,
|
||||
[[NSUUID alloc] initWithUUIDString:discountMap[@"nonce"]]);
|
||||
XCTAssertEqual(paymentDiscount.signature, discountMap[@"signature"]);
|
||||
XCTAssertEqual(paymentDiscount.timestamp, discountMap[@"timestamp"]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSKPaymentDiscountConvertToPigeon {
|
||||
if (@available(iOS 12.2, *)) {
|
||||
NSString *error = nil;
|
||||
SKPaymentDiscount *paymentDiscount =
|
||||
[FIAObjectTranslator getSKPaymentDiscountFromMap:self.paymentDiscountMap withError:&error];
|
||||
SKPaymentDiscountMessage *paymentDiscountPigeon =
|
||||
[FIAObjectTranslator convertPaymentDiscountToPigeon:paymentDiscount];
|
||||
|
||||
XCTAssertNotNil(paymentDiscountPigeon);
|
||||
XCTAssertEqual(paymentDiscount.identifier, paymentDiscountPigeon.identifier);
|
||||
XCTAssertEqual(paymentDiscount.keyIdentifier, paymentDiscount.keyIdentifier);
|
||||
XCTAssertEqualObjects(paymentDiscount.nonce,
|
||||
[[NSUUID alloc] initWithUUIDString:paymentDiscountPigeon.nonce]);
|
||||
XCTAssertEqual(paymentDiscount.signature, paymentDiscountPigeon.signature);
|
||||
XCTAssertEqual([paymentDiscount.timestamp intValue], paymentDiscountPigeon.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSKErrorConvertToPigeon {
|
||||
NSError *error = [NSError errorWithDomain:SKErrorDomain code:3 userInfo:@{@"key" : @42}];
|
||||
SKErrorMessage *msg = [SKErrorMessage makeWithCode:3
|
||||
domain:SKErrorDomain
|
||||
userInfo:@{@"key" : @42}];
|
||||
|
||||
SKErrorMessage *skerror = [FIAObjectTranslator convertSKErrorToPigeon:error];
|
||||
XCTAssertEqual(skerror.domain, msg.domain);
|
||||
XCTAssertEqual(skerror.code, msg.code);
|
||||
XCTAssertEqualObjects(skerror.userInfo, msg.userInfo);
|
||||
}
|
||||
|
||||
- (void)testSKPaymentConvertToPigeon {
|
||||
if (@available(iOS 12.2, *)) {
|
||||
SKMutablePayment *payment = [FIAObjectTranslator getSKMutablePaymentFromMap:self.paymentMap];
|
||||
SKPaymentMessage *msg = [FIAObjectTranslator convertPaymentToPigeon:payment];
|
||||
|
||||
XCTAssertEqual(payment.productIdentifier, msg.productIdentifier);
|
||||
XCTAssertEqualObjects(payment.requestData,
|
||||
[msg.requestData dataUsingEncoding:NSUTF8StringEncoding]);
|
||||
XCTAssertEqual(payment.quantity, msg.quantity);
|
||||
XCTAssertEqual(payment.applicationUsername, msg.applicationUsername);
|
||||
XCTAssertEqual(payment.simulatesAskToBuyInSandbox, msg.simulatesAskToBuyInSandbox);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSKPaymentTransactionConvertToPigeon {
|
||||
SKPaymentTransactionStub *paymentTransaction =
|
||||
[[SKPaymentTransactionStub alloc] initWithMap:self.transactionMap];
|
||||
|
||||
SKPaymentTransactionMessage *msg =
|
||||
[FIAObjectTranslator convertTransactionToPigeon:paymentTransaction];
|
||||
|
||||
XCTAssertEqual(msg.payment, NULL);
|
||||
XCTAssertEqual(msg.transactionState, SKPaymentTransactionStateMessagePurchasing);
|
||||
XCTAssertEqual(paymentTransaction.transactionDate,
|
||||
[NSDate dateWithTimeIntervalSince1970:[msg.transactionTimeStamp doubleValue]]);
|
||||
XCTAssertEqual(paymentTransaction.transactionIdentifier, msg.transactionIdentifier);
|
||||
}
|
||||
|
||||
- (void)testSKProductResponseCovertToPigeon {
|
||||
SKProductsResponseStub *response =
|
||||
[[SKProductsResponseStub alloc] initWithMap:self.productResponseMap];
|
||||
SKProductsResponseMessage *responseMsg =
|
||||
[FIAObjectTranslator convertProductsResponseToPigeon:response];
|
||||
|
||||
XCTAssertEqual(responseMsg.products.count, 1);
|
||||
XCTAssertEqual(responseMsg.invalidProductIdentifiers.count, 0);
|
||||
|
||||
SKProductMessage *productMsg = responseMsg.products[0];
|
||||
|
||||
// These values are being set in productResponseMap in setUp()
|
||||
XCTAssertEqualObjects(productMsg.price, @"1");
|
||||
XCTAssertEqualObjects(productMsg.productIdentifier, @"123");
|
||||
XCTAssertEqualObjects(productMsg.localizedTitle, @"title");
|
||||
XCTAssertEqualObjects(productMsg.localizedDescription, @"des");
|
||||
XCTAssertEqualObjects(productMsg.subscriptionGroupIdentifier, @"com.group");
|
||||
|
||||
SKPriceLocaleMessage *localeMsg = productMsg.priceLocale;
|
||||
SKProductSubscriptionPeriodMessage *subPeriod = productMsg.subscriptionPeriod;
|
||||
SKProductDiscountMessage *introDiscount = productMsg.introductoryPrice;
|
||||
NSArray<SKProductDiscountMessage *> *discounts = productMsg.discounts;
|
||||
|
||||
XCTAssertEqualObjects(localeMsg.countryCode, nil);
|
||||
XCTAssertEqualObjects(localeMsg.currencyCode, nil);
|
||||
XCTAssertEqualObjects(localeMsg.currencySymbol, @"\u00a4");
|
||||
|
||||
XCTAssertEqual(subPeriod.unit, SKSubscriptionPeriodUnitMessageDay);
|
||||
XCTAssertEqual(subPeriod.numberOfUnits, 0);
|
||||
|
||||
XCTAssertEqualObjects(introDiscount.price, @"1");
|
||||
XCTAssertEqual(introDiscount.numberOfPeriods, 1);
|
||||
XCTAssertEqual(introDiscount.paymentMode, SKProductDiscountPaymentModeMessagePayUpFront);
|
||||
|
||||
XCTAssertEqual(discounts.count, 1);
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,551 @@
|
||||
// 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 Foundation
|
||||
import StoreKit
|
||||
import XCTest
|
||||
|
||||
@testable import in_app_purchase_storekit
|
||||
|
||||
final class ObjectTranslatorTest: XCTestCase {
|
||||
private var periodMap: [String: Any] {
|
||||
["numberOfUnits": 0, "unit": 0]
|
||||
}
|
||||
private var discountMap: [String: Any] {
|
||||
var map: [String: Any] = [
|
||||
"price": "1",
|
||||
"priceLocale": FIAObjectTranslator.getMapFrom(NSLocale.system),
|
||||
"numberOfPeriods": 1,
|
||||
"subscriptionPeriod": periodMap,
|
||||
"paymentMode": 1,
|
||||
]
|
||||
if #available(iOS 12.2, *) {
|
||||
map["identifier"] = "test offer id"
|
||||
// Type is being instantiated like this because of Swift naming weirdness
|
||||
let type: SKProductDiscount.`Type` = .introductory
|
||||
map["type"] = type.rawValue
|
||||
}
|
||||
return map
|
||||
}
|
||||
private var discountMissingIdentifierMap: [String: Any] {
|
||||
[
|
||||
"price": "1",
|
||||
"priceLocale": FIAObjectTranslator.getMapFrom(NSLocale.system),
|
||||
"numberOfPeriods": 1,
|
||||
"subscriptionPeriod": periodMap,
|
||||
"paymentMode": 1,
|
||||
"identifier": NSNull(),
|
||||
"type": 0,
|
||||
]
|
||||
}
|
||||
private var productMap: [String: Any] {
|
||||
var map: [String: Any] = [
|
||||
"price": "1",
|
||||
"priceLocale": FIAObjectTranslator.getMapFrom(NSLocale.system),
|
||||
"productIdentifier": "123",
|
||||
"localizedTitle": "title",
|
||||
"localizedDescription": "des",
|
||||
"subscriptionPeriod": periodMap,
|
||||
"introductoryPrice": discountMap,
|
||||
"subscriptionGroupIdentifier": "com.group",
|
||||
]
|
||||
if #available(iOS 12.2, *) {
|
||||
map["discounts"] = [discountMap]
|
||||
}
|
||||
return map
|
||||
}
|
||||
private var productResponseMap: [String: Any] {
|
||||
["products": [productMap], "invalidProductIdentifiers": []]
|
||||
}
|
||||
private var paymentMap: [String: Any] {
|
||||
[
|
||||
"productIdentifier": "123",
|
||||
"requestData": "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
|
||||
"quantity": 2,
|
||||
"applicationUsername": "app user name",
|
||||
"simulatesAskToBuyInSandbox": false,
|
||||
]
|
||||
}
|
||||
private var paymentDiscountMap: [String: Any] {
|
||||
[
|
||||
"identifier": "payment_discount_identifier",
|
||||
"keyIdentifier": "payment_discount_key_identifier",
|
||||
"nonce": "d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
"signature": "this is an encrypted signature",
|
||||
"timestamp": Int(Date().timeIntervalSince1970),
|
||||
]
|
||||
}
|
||||
private var transactionMap: [String: Any] {
|
||||
[
|
||||
"transactionIdentifier": "567",
|
||||
"transactionState": SKPaymentTransactionState.purchasing.rawValue,
|
||||
"payment": NSNull(),
|
||||
"error": FIAObjectTranslator.getMapFrom(
|
||||
NSError(domain: "test_stub", code: 123, userInfo: [:])),
|
||||
"transactionTimeStamp": Int(Date().timeIntervalSince1970),
|
||||
"originalTransaction": originalTransactionMap,
|
||||
]
|
||||
}
|
||||
private var originalTransactionMap: [String: Any] {
|
||||
[
|
||||
"transactionIdentifier": "567",
|
||||
"transactionState": SKPaymentTransactionState.purchasing.rawValue,
|
||||
"payment": NSNull(),
|
||||
"error": FIAObjectTranslator.getMapFrom(
|
||||
NSError(domain: "test_stub", code: 123, userInfo: [:])),
|
||||
"transactionTimeStamp": Int(Date().timeIntervalSince1970),
|
||||
"originalTransaction": NSNull(),
|
||||
]
|
||||
}
|
||||
private var errorMap: [String: Any] {
|
||||
[
|
||||
"code": 123,
|
||||
"domain": "test_domain",
|
||||
"userInfo": ["key": "value"],
|
||||
]
|
||||
}
|
||||
private var storefrontMap: [String: Any] {
|
||||
[
|
||||
"countryCode": "USA",
|
||||
"identifier": "unique_identifier",
|
||||
]
|
||||
}
|
||||
private var storefrontAndPaymentTransactionMap: [String: Any] {
|
||||
[
|
||||
"storefront": storefrontMap,
|
||||
"transaction": transactionMap,
|
||||
]
|
||||
}
|
||||
|
||||
func testSKProductSubscriptionPeriodStubToMap() {
|
||||
let period = SKProductSubscriptionPeriodStub(map: periodMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(period)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, periodMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testSKProductDiscountStubToMap() {
|
||||
let discount = SKProductDiscountStub(map: discountMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(discount)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, discountMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testProductToMap() {
|
||||
let product = SKProductStub(map: productMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(product)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, productMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testProductResponseToMap() {
|
||||
let response = SKProductsResponseStub(map: productResponseMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(response)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, productResponseMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testPaymentToMap() {
|
||||
let payment = FIAObjectTranslator.getSKMutablePayment(fromMap: paymentMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(payment)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, paymentMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testPaymentTransactionToMap() {
|
||||
let paymentTransaction = SKPaymentTransactionStub(map: transactionMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(paymentTransaction)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, transactionMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testError() {
|
||||
let error = NSErrorStub(map: errorMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(error)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, errorMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testErrorWithNSNumberAsUserInfo() {
|
||||
let error = NSError(domain: SKErrorDomain, code: 3, userInfo: ["key": 42])
|
||||
let expectedMap: [String: Any] = [
|
||||
"domain": SKErrorDomain,
|
||||
"code": 3,
|
||||
"userInfo": ["key": 42],
|
||||
]
|
||||
let map = FIAObjectTranslator.getMapFrom(error)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, expectedMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testErrorWithMultipleUnderlyingErrors() {
|
||||
let underlyingErrorOne = NSError(domain: SKErrorDomain, code: 2, userInfo: nil)
|
||||
let underlyingErrorTwo = NSError(domain: SKErrorDomain, code: 1, userInfo: nil)
|
||||
let mainError = NSError(
|
||||
domain: SKErrorDomain,
|
||||
code: 3,
|
||||
userInfo: ["underlyingErrors": [underlyingErrorOne, underlyingErrorTwo]]
|
||||
)
|
||||
let expectedMap: [String: Any] = [
|
||||
"domain": SKErrorDomain,
|
||||
"code": 3,
|
||||
"userInfo": [
|
||||
"underlyingErrors": [
|
||||
["domain": SKErrorDomain, "code": 2, "userInfo": [:]],
|
||||
["domain": SKErrorDomain, "code": 1, "userInfo": [:]],
|
||||
]
|
||||
],
|
||||
]
|
||||
let map = FIAObjectTranslator.getMapFrom(mainError)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, expectedMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testErrorWithNestedUnderlyingError() {
|
||||
let underlyingError = NSError(domain: SKErrorDomain, code: 2, userInfo: nil)
|
||||
let mainError = NSError(
|
||||
domain: SKErrorDomain,
|
||||
code: 3,
|
||||
userInfo: ["nesting": ["underlyingError": underlyingError]]
|
||||
)
|
||||
let expectedMap: [String: Any] = [
|
||||
"domain": SKErrorDomain,
|
||||
"code": 3,
|
||||
"userInfo": [
|
||||
"nesting": [
|
||||
"underlyingError": ["domain": SKErrorDomain, "code": 2, "userInfo": [:]]
|
||||
]
|
||||
],
|
||||
]
|
||||
let map = FIAObjectTranslator.getMapFrom(mainError)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, expectedMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testErrorWithUnsupportedUserInfo() {
|
||||
let error = NSError(
|
||||
domain: SKErrorDomain,
|
||||
code: 3,
|
||||
userInfo: ["user_info": NSObject()]
|
||||
)
|
||||
let expectedMap: [String: Any] = [
|
||||
"domain": SKErrorDomain,
|
||||
"code": 3,
|
||||
"userInfo": [
|
||||
"user_info": String(
|
||||
format: """
|
||||
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.
|
||||
""",
|
||||
NSStringFromClass(NSObject.self), NSStringFromClass(NSObject.self)
|
||||
)
|
||||
],
|
||||
]
|
||||
let map = FIAObjectTranslator.getMapFrom(error)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, expectedMap as NSDictionary)
|
||||
}
|
||||
|
||||
func testLocaleToMap() {
|
||||
let system = Locale(identifier: "en_US")
|
||||
let map = FIAObjectTranslator.getMapFrom(system)
|
||||
|
||||
XCTAssertEqual(map["currencySymbol"] as? String, system.currencySymbol)
|
||||
XCTAssertEqual(map["countryCode"] as? String, system.regionCode)
|
||||
}
|
||||
|
||||
func testSKStorefrontToMap() {
|
||||
if #available(iOS 13.0, *) {
|
||||
let storefront = SKStorefrontStub(map: storefrontMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(storefront)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, storefrontMap as NSDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKStorefrontAndSKPaymentTransactionToMap() {
|
||||
if #available(iOS 13.0, *) {
|
||||
let storefront = SKStorefrontStub(map: storefrontMap)
|
||||
let transaction = SKPaymentTransactionStub(map: transactionMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(storefront, andSKPaymentTransaction: transaction)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, storefrontAndPaymentTransactionMap as NSDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMap() throws {
|
||||
if #available(iOS 12.2, *) {
|
||||
var error: NSString?
|
||||
let paymentDiscount = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: paymentDiscountMap, withError: &error)
|
||||
|
||||
XCTAssertNil(error)
|
||||
|
||||
let unwrappedDiscount = try XCTUnwrap(paymentDiscount)
|
||||
let unwrappedNonce = try XCTUnwrap(paymentDiscountMap["nonce"] as? String)
|
||||
|
||||
XCTAssertEqual(unwrappedDiscount.identifier, paymentDiscountMap["identifier"] as? String)
|
||||
XCTAssertEqual(
|
||||
unwrappedDiscount.keyIdentifier, paymentDiscountMap["keyIdentifier"] as? String)
|
||||
XCTAssertEqual(
|
||||
unwrappedDiscount.nonce, UUID(uuidString: unwrappedNonce))
|
||||
XCTAssertEqual(unwrappedDiscount.signature, paymentDiscountMap["signature"] as? String)
|
||||
XCTAssertEqual(unwrappedDiscount.timestamp as? Int, paymentDiscountMap["timestamp"] as? Int)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMapMissingIdentifier() {
|
||||
if #available(iOS 12.2, *) {
|
||||
let invalidValues: [Any?] = [NSNull(), 1, ""]
|
||||
for value in invalidValues {
|
||||
let discountMap: [String: Any?] = [
|
||||
"identifier": value,
|
||||
"keyIdentifier": "payment_discount_key_identifier",
|
||||
"nonce": "d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
"signature": "this is an encrypted signature",
|
||||
"timestamp": Int(Date().timeIntervalSince1970),
|
||||
]
|
||||
var error: NSString?
|
||||
let _ = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: discountMap as [String: Any], withError: &error)
|
||||
|
||||
XCTAssertNotNil(error)
|
||||
XCTAssertEqual(
|
||||
error, "When specifying a payment discount the 'identifier' field is mandatory.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGetMapFromSKProductDiscountMissingIdentifier() {
|
||||
if #available(iOS 12.2, *) {
|
||||
let discount = SKProductDiscountStub(map: discountMissingIdentifierMap)
|
||||
let map = FIAObjectTranslator.getMapFrom(discount)
|
||||
|
||||
XCTAssertEqual(map as NSDictionary, discountMissingIdentifierMap as NSDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMapMissingKeyIdentifier() {
|
||||
if #available(iOS 12.2, *) {
|
||||
let invalidValues: [Any?] = [NSNull(), 1, ""]
|
||||
for value in invalidValues {
|
||||
let discountMap: [String: Any?] = [
|
||||
"identifier": "payment_discount_identifier",
|
||||
"keyIdentifier": value,
|
||||
"nonce": "d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
"signature": "this is an encrypted signature",
|
||||
"timestamp": Int(Date().timeIntervalSince1970),
|
||||
]
|
||||
var error: NSString?
|
||||
let _ = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: discountMap as [String: Any], withError: &error)
|
||||
|
||||
XCTAssertNotNil(error)
|
||||
XCTAssertEqual(
|
||||
error, "When specifying a payment discount the 'keyIdentifier' field is mandatory.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMapMissingNonce() {
|
||||
if #available(iOS 12.2, *) {
|
||||
let invalidValues: [Any?] = [NSNull(), 1, ""]
|
||||
for value in invalidValues {
|
||||
let discountMap: [String: Any?] = [
|
||||
"identifier": "payment_discount_identifier",
|
||||
"keyIdentifier": "payment_discount_key_identifier",
|
||||
"nonce": value,
|
||||
"signature": "this is an encrypted signature",
|
||||
"timestamp": Int(Date().timeIntervalSince1970),
|
||||
]
|
||||
var error: NSString?
|
||||
let _ = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: discountMap as [String: Any], withError: &error)
|
||||
|
||||
XCTAssertNotNil(error)
|
||||
XCTAssertEqual(error, "When specifying a payment discount the 'nonce' field is mandatory.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMapMissingSignature() {
|
||||
if #available(iOS 12.2, *) {
|
||||
let invalidValues: [Any?] = [NSNull(), 1, ""]
|
||||
for value in invalidValues {
|
||||
let discountMap: [String: Any?] = [
|
||||
"identifier": "payment_discount_identifier",
|
||||
"keyIdentifier": "payment_discount_key_identifier",
|
||||
"nonce": "d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
"signature": value,
|
||||
"timestamp": Int(Date().timeIntervalSince1970),
|
||||
]
|
||||
var error: NSString?
|
||||
let _ = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: discountMap as [String: Any], withError: &error)
|
||||
|
||||
XCTAssertNotNil(error)
|
||||
XCTAssertEqual(
|
||||
error, "When specifying a payment discount the 'signature' field is mandatory.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMapMissingTimestamp() {
|
||||
if #available(iOS 12.2, *) {
|
||||
let invalidValues: [Any?] = [NSNull(), "", -1]
|
||||
for value in invalidValues {
|
||||
let discountMap: [String: Any?] = [
|
||||
"identifier": "payment_discount_identifier",
|
||||
"keyIdentifier": "payment_discount_key_identifier",
|
||||
"nonce": "d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
"signature": "this is an encrypted signature",
|
||||
"timestamp": value,
|
||||
]
|
||||
var error: NSString?
|
||||
let _ = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: discountMap as [String: Any], withError: &error)
|
||||
|
||||
XCTAssertNotNil(error)
|
||||
XCTAssertEqual(
|
||||
error, "When specifying a payment discount the 'timestamp' field is mandatory.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountFromMapOverflowingTimestamp() throws {
|
||||
if #available(iOS 12.2, *) {
|
||||
let discountMap: [String: Any] = [
|
||||
"identifier": "payment_discount_identifier",
|
||||
"keyIdentifier": "payment_discount_key_identifier",
|
||||
"nonce": "d18981e0-9003-4365-98a2-4b90e3b62c52",
|
||||
"signature": "this is an encrypted signature",
|
||||
"timestamp": 1_665_044_583_595, // timestamp 2022 Oct
|
||||
]
|
||||
var error: NSString?
|
||||
let paymentDiscount = FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: discountMap, withError: &error)
|
||||
XCTAssertNil(error)
|
||||
|
||||
let unwrappedPaymentDiscount = try XCTUnwrap(paymentDiscount)
|
||||
let identifier = try XCTUnwrap(discountMap["identifier"] as? String)
|
||||
XCTAssertEqual(unwrappedPaymentDiscount.identifier, identifier)
|
||||
|
||||
let keyIdentifier = try XCTUnwrap(discountMap["keyIdentifier"] as? String)
|
||||
XCTAssertEqual(unwrappedPaymentDiscount.keyIdentifier, keyIdentifier)
|
||||
|
||||
let nonceString = try XCTUnwrap(discountMap["nonce"] as? String)
|
||||
let nonce = try XCTUnwrap(UUID(uuidString: nonceString))
|
||||
XCTAssertEqual(unwrappedPaymentDiscount.nonce, nonce)
|
||||
|
||||
let signature = try XCTUnwrap(discountMap["signature"] as? String)
|
||||
XCTAssertEqual(unwrappedPaymentDiscount.signature, signature)
|
||||
|
||||
let timestamp = try XCTUnwrap(discountMap["timestamp"] as? Int)
|
||||
XCTAssertEqual(unwrappedPaymentDiscount.timestamp as? Int, timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentDiscountConvertToPigeon() throws {
|
||||
if #available(iOS 12.2, *) {
|
||||
var error: NSString?
|
||||
let paymentDiscount = try XCTUnwrap(
|
||||
FIAObjectTranslator.getSKPaymentDiscount(
|
||||
fromMap: paymentDiscountMap, withError: &error))
|
||||
let paymentDiscountPigeon = try XCTUnwrap(
|
||||
FIAObjectTranslator.convertPaymentDiscount(
|
||||
toPigeon: paymentDiscount))
|
||||
|
||||
XCTAssertNotNil(paymentDiscountPigeon)
|
||||
XCTAssertEqual(paymentDiscount.identifier, paymentDiscountPigeon.identifier)
|
||||
XCTAssertEqual(paymentDiscount.keyIdentifier, paymentDiscount.keyIdentifier)
|
||||
XCTAssertEqual(paymentDiscount.nonce, UUID(uuidString: paymentDiscountPigeon.nonce))
|
||||
XCTAssertEqual(paymentDiscount.signature, paymentDiscountPigeon.signature)
|
||||
|
||||
let paymentDiscountTimestamp = paymentDiscount.timestamp as? Int
|
||||
let paymentDiscountPigeonTimestamp = paymentDiscountPigeon.timestamp
|
||||
|
||||
XCTAssertEqual(paymentDiscountTimestamp, paymentDiscountPigeonTimestamp)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKErrorConvertToPigeon() throws {
|
||||
let error = NSError(domain: SKErrorDomain, code: 3, userInfo: ["key": 42])
|
||||
let msg = SKErrorMessage.make(
|
||||
withCode: 3, domain: SKErrorDomain, userInfo: ["key": 42] as [String: Any])
|
||||
let skerror = try XCTUnwrap(FIAObjectTranslator.convertSKError(toPigeon: error))
|
||||
|
||||
XCTAssertEqual(skerror.domain, msg.domain)
|
||||
XCTAssertEqual(skerror.code, msg.code)
|
||||
|
||||
let skerrorUserInfo = skerror.userInfo
|
||||
let msgUserInfo = try XCTUnwrap(msg.userInfo)
|
||||
|
||||
XCTAssertEqual(skerrorUserInfo as NSDictionary?, msgUserInfo as NSDictionary)
|
||||
}
|
||||
|
||||
func testSKPaymentConvertToPigeon() throws {
|
||||
if #available(iOS 12.2, *) {
|
||||
let payment = FIAObjectTranslator.getSKMutablePayment(fromMap: paymentMap)
|
||||
let msg = try XCTUnwrap(FIAObjectTranslator.convertPayment(toPigeon: payment))
|
||||
let msgRequestData = try XCTUnwrap(msg.requestData)
|
||||
|
||||
XCTAssertEqual(payment.productIdentifier, msg.productIdentifier)
|
||||
XCTAssertEqual(payment.requestData, msgRequestData.data(using: .utf8))
|
||||
XCTAssertEqual(payment.quantity, msg.quantity)
|
||||
XCTAssertEqual(payment.applicationUsername, msg.applicationUsername)
|
||||
XCTAssertEqual(payment.simulatesAskToBuyInSandbox, msg.simulatesAskToBuyInSandbox)
|
||||
}
|
||||
}
|
||||
|
||||
func testSKPaymentTransactionConvertToPigeon() throws {
|
||||
let paymentTransaction = SKPaymentTransactionStub(map: transactionMap)
|
||||
let msg = FIAObjectTranslator.convertTransaction(toPigeon: paymentTransaction)
|
||||
|
||||
let unwrappedMsg = try XCTUnwrap(msg)
|
||||
let unwrappedTimeStamp = try XCTUnwrap(unwrappedMsg.transactionTimeStamp)
|
||||
|
||||
XCTAssertEqual(unwrappedMsg.transactionState, SKPaymentTransactionStateMessage.purchasing)
|
||||
XCTAssertEqual(
|
||||
paymentTransaction.transactionDate,
|
||||
Date(timeIntervalSince1970: TimeInterval(truncating: unwrappedTimeStamp)))
|
||||
XCTAssertEqual(paymentTransaction.transactionIdentifier, unwrappedMsg.transactionIdentifier)
|
||||
}
|
||||
|
||||
func testSKProductResponseCovertToPigeon() throws {
|
||||
let response = SKProductsResponseStub(map: productResponseMap)
|
||||
let responseMsg = FIAObjectTranslator.convertProductsResponse(toPigeon: response)
|
||||
let unwrappedMsg = try XCTUnwrap(responseMsg)
|
||||
|
||||
let products = try XCTUnwrap(unwrappedMsg.products)
|
||||
XCTAssertEqual(products.count, 1)
|
||||
|
||||
let invalidProductIdentifiers = try XCTUnwrap(unwrappedMsg.invalidProductIdentifiers)
|
||||
XCTAssertTrue(invalidProductIdentifiers.isEmpty)
|
||||
|
||||
let productMsg = try XCTUnwrap(unwrappedMsg.products?.first)
|
||||
XCTAssertEqual(productMsg.productIdentifier, "123")
|
||||
XCTAssertEqual(productMsg.localizedTitle, "title")
|
||||
XCTAssertEqual(productMsg.localizedDescription, "des")
|
||||
XCTAssertEqual(productMsg.subscriptionGroupIdentifier, "com.group")
|
||||
|
||||
let localeMsg = try XCTUnwrap(productMsg.priceLocale)
|
||||
XCTAssertEqual(localeMsg.countryCode, "")
|
||||
XCTAssertEqual(localeMsg.currencyCode, "")
|
||||
XCTAssertEqual(localeMsg.currencySymbol, "\u{00a4}")
|
||||
|
||||
let subPeriod = try XCTUnwrap(productMsg.subscriptionPeriod)
|
||||
XCTAssertEqual(subPeriod.unit, SKSubscriptionPeriodUnitMessage.day)
|
||||
XCTAssertEqual(subPeriod.numberOfUnits, 0)
|
||||
|
||||
let introDiscount = try XCTUnwrap(productMsg.introductoryPrice)
|
||||
XCTAssertEqual(introDiscount.price, "1")
|
||||
XCTAssertEqual(introDiscount.numberOfPeriods, 1)
|
||||
XCTAssertEqual(introDiscount.paymentMode, SKProductDiscountPaymentModeMessage.payUpFront)
|
||||
|
||||
let discounts = try XCTUnwrap(productMsg.discounts)
|
||||
XCTAssertEqual(discounts.count, 1)
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ name: in_app_purchase_storekit
|
||||
description: An implementation for the iOS and macOS platforms of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework.
|
||||
repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase_storekit
|
||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
|
||||
version: 0.3.17+2
|
||||
version: 0.3.17+3
|
||||
|
||||
environment:
|
||||
sdk: ^3.2.3
|
||||
|
Reference in New Issue
Block a user