diff --git a/Package.resolved b/Package.resolved index ab65af5512..44d00852ea 100644 --- a/Package.resolved +++ b/Package.resolved @@ -18,6 +18,15 @@ "version" : "2.2.2" } }, + { + "identity" : "flyingfox", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swhitty/FlyingFox.git", + "state" : { + "revision" : "f7829d4aca8cbfecb410a1cce872b1b045224aa1", + "version" : "0.16.0" + } + }, { "identity" : "nimble", "kind" : "remoteSourceControl", @@ -27,6 +36,33 @@ "version" : "13.7.1" } }, + { + "identity" : "ohhttpstubs", + "kind" : "remoteSourceControl", + "location" : "https://github.com/AliSoftware/OHHTTPStubs.git", + "state" : { + "revision" : "12f19662426d0434d6c330c6974d53e2eb10ecd9", + "version" : "9.1.0" + } + }, + { + "identity" : "simpledebugger", + "kind" : "remoteSourceControl", + "location" : "https://github.com/EmergeTools/SimpleDebugger.git", + "state" : { + "revision" : "f065263eb5db95874b690408d136b573c939db9e", + "version" : "1.0.0" + } + }, + { + "identity" : "snapshotpreviews", + "kind" : "remoteSourceControl", + "location" : "https://github.com/EmergeTools/SnapshotPreviews.git", + "state" : { + "revision" : "6dfb281493e48e7c09ae9717593ae0b8eb47b15c", + "version" : "0.11.0" + } + }, { "identity" : "swift-custom-dump", "kind" : "remoteSourceControl", diff --git a/RevenueCat.xcodeproj/project.pbxproj b/RevenueCat.xcodeproj/project.pbxproj index fffdbcdf83..a156394d67 100644 --- a/RevenueCat.xcodeproj/project.pbxproj +++ b/RevenueCat.xcodeproj/project.pbxproj @@ -742,7 +742,6 @@ 5791FE4A2994453500F1FEDA /* Signing+ResponseVerification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5791FE492994453500F1FEDA /* Signing+ResponseVerification.swift */; }; 579234E327F7788900B39C68 /* BaseBackendIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 579234E127F777EE00B39C68 /* BaseBackendIntegrationTests.swift */; }; 579234E527F779FE00B39C68 /* SubscriberAttributesManagerIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 579234E427F779FE00B39C68 /* SubscriberAttributesManagerIntegrationTests.swift */; }; - EF970D13102945639A882001 /* ATTConsentStatusIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF970D13102945639A882002 /* ATTConsentStatusIntegrationTests.swift */; }; 5793397028E77A5100C1232C /* PaymentQueueWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5793396F28E77A5100C1232C /* PaymentQueueWrapperTests.swift */; }; 5793397228E77A6E00C1232C /* MockPaymentQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5793397128E77A6E00C1232C /* MockPaymentQueue.swift */; }; 579415D2293689DD00218FBC /* Codable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 579415D1293689DD00218FBC /* Codable+Extensions.swift */; }; @@ -1320,12 +1319,25 @@ B3F8418F26F3A93400E560FB /* ErrorCodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3F8418E26F3A93400E560FB /* ErrorCodeTests.swift */; }; C074AAE036B449898E1FEF58 /* CustomPaywallVariables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B46553B99148F3A60B8BFB /* CustomPaywallVariables.swift */; }; D0DA209A2F23BBEC00BA3B77 /* AdEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DA20992F23BBEC00BA3B77 /* AdEventTests.swift */; }; + DB3395CA2F840A2B0079250C /* WorkflowsCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395C92F840A2B0079250C /* WorkflowsCallback.swift */; }; + DB3395D22F840A400079250C /* GetWorkflowsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395D12F840A400079250C /* GetWorkflowsOperation.swift */; }; + DB3395D32F840A400079250C /* GetWorkflowOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395D02F840A400079250C /* GetWorkflowOperation.swift */; }; + DB3395D52F840A570079250C /* WorkflowsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395D42F840A570079250C /* WorkflowsResponse.swift */; }; + DB3395DB2F840A790079250C /* WorkflowDetailProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395D82F840A790079250C /* WorkflowDetailProcessor.swift */; }; + DB3395DD2F840A790079250C /* WorkflowResponseAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395D92F840A790079250C /* WorkflowResponseAction.swift */; }; + DB3395E12F840AA60079250C /* WorkflowsAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395E02F840AA60079250C /* WorkflowsAPI.swift */; }; + DB3395E32F840ACD0079250C /* BackendGetWorkflowsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395E22F840ACD0079250C /* BackendGetWorkflowsTests.swift */; }; + DB3395E72F840ADA0079250C /* WorkflowResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395E52F840ADA0079250C /* WorkflowResponseTests.swift */; }; + DB3395E82F840ADA0079250C /* WorkflowDetailProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3395E42F840ADA0079250C /* WorkflowDetailProcessorTests.swift */; }; DB36994E2F435CDC00B1F049 /* PriceFormatterExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB36994D2F435CDC00B1F049 /* PriceFormatterExtensions.swift */; }; DB55E6262ECE012600636909 /* FlexSpacer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB55E6252ECE012600636909 /* FlexSpacer.swift */; }; + DBAA1FA82F88EAEB000E8C81 /* MockWorkflowsAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAA1FA72F88EAEB000E8C81 /* MockWorkflowsAPI.swift */; }; + DBAA1FA92F88EAEB000E8C81 /* MockWorkflowsAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAA1FA72F88EAEB000E8C81 /* MockWorkflowsAPI.swift */; }; DBD2432F2EBDF4BC0066AC6F /* PromotionalOfferViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD243292EBDF4B80066AC6F /* PromotionalOfferViewTests.swift */; }; DBE7C6552F02D48900A28663 /* StoreProductDiscount+CustomerCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE7C6542F02D48900A28663 /* StoreProductDiscount+CustomerCenter.swift */; }; DDD45A15A641C0FF0BEF6178 /* PaywallCountdownComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1A05E9E1B04B32B832DB194 /* PaywallCountdownComponent.swift */; }; ED85C2AB8EAB82D346A12569 /* CarouselStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B29E428C04E073334CD13B58 /* CarouselStateTests.swift */; }; + EF970D13102945639A882001 /* ATTConsentStatusIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF970D13102945639A882002 /* ATTConsentStatusIntegrationTests.swift */; }; F516BD29282434070083480B /* StoreKit2StorefrontListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = F516BD28282434070083480B /* StoreKit2StorefrontListener.swift */; }; F52CFAFC28290AE500E8ABC5 /* StoreKit2StorefrontListenerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F516BD322828FDD90083480B /* StoreKit2StorefrontListenerTests.swift */; }; F530E4FF275646EF001AF6BD /* MacDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = F530E4FE275646EF001AF6BD /* MacDevice.swift */; }; @@ -2321,7 +2333,6 @@ 5791FE492994453500F1FEDA /* Signing+ResponseVerification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Signing+ResponseVerification.swift"; sourceTree = ""; }; 579234E127F777EE00B39C68 /* BaseBackendIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseBackendIntegrationTests.swift; sourceTree = ""; }; 579234E427F779FE00B39C68 /* SubscriberAttributesManagerIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriberAttributesManagerIntegrationTests.swift; sourceTree = ""; }; - EF970D13102945639A882002 /* ATTConsentStatusIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTConsentStatusIntegrationTests.swift; sourceTree = ""; }; 5793396F28E77A5100C1232C /* PaymentQueueWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentQueueWrapperTests.swift; sourceTree = ""; }; 5793397128E77A6E00C1232C /* MockPaymentQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPaymentQueue.swift; sourceTree = ""; }; 579415D1293689DD00218FBC /* Codable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Codable+Extensions.swift"; sourceTree = ""; }; @@ -2857,10 +2868,22 @@ B3F8418E26F3A93400E560FB /* ErrorCodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorCodeTests.swift; sourceTree = ""; }; CC1A2B3C2E1234AB00AABBCC /* CustomVariablesEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomVariablesEditorView.swift; sourceTree = ""; }; D0DA20992F23BBEC00BA3B77 /* AdEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdEventTests.swift; sourceTree = ""; }; + DB3395C92F840A2B0079250C /* WorkflowsCallback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowsCallback.swift; sourceTree = ""; }; + DB3395D02F840A400079250C /* GetWorkflowOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetWorkflowOperation.swift; sourceTree = ""; }; + DB3395D12F840A400079250C /* GetWorkflowsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetWorkflowsOperation.swift; sourceTree = ""; }; + DB3395D42F840A570079250C /* WorkflowsResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowsResponse.swift; sourceTree = ""; }; + DB3395D82F840A790079250C /* WorkflowDetailProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowDetailProcessor.swift; sourceTree = ""; }; + DB3395D92F840A790079250C /* WorkflowResponseAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowResponseAction.swift; sourceTree = ""; }; + DB3395E02F840AA60079250C /* WorkflowsAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowsAPI.swift; sourceTree = ""; }; + DB3395E22F840ACD0079250C /* BackendGetWorkflowsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackendGetWorkflowsTests.swift; sourceTree = ""; }; + DB3395E42F840ADA0079250C /* WorkflowDetailProcessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowDetailProcessorTests.swift; sourceTree = ""; }; + DB3395E52F840ADA0079250C /* WorkflowResponseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkflowResponseTests.swift; sourceTree = ""; }; DB36994D2F435CDC00B1F049 /* PriceFormatterExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceFormatterExtensions.swift; sourceTree = ""; }; DB55E6252ECE012600636909 /* FlexSpacer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlexSpacer.swift; sourceTree = ""; }; + DBAA1FA72F88EAEB000E8C81 /* MockWorkflowsAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockWorkflowsAPI.swift; sourceTree = ""; }; DBD243292EBDF4B80066AC6F /* PromotionalOfferViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromotionalOfferViewTests.swift; sourceTree = ""; }; DBE7C6542F02D48900A28663 /* StoreProductDiscount+CustomerCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StoreProductDiscount+CustomerCenter.swift"; sourceTree = ""; }; + EF970D13102945639A882002 /* ATTConsentStatusIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTConsentStatusIntegrationTests.swift; sourceTree = ""; }; EFB3CBAA73855779FE828CE2 /* ProductsFetcherSK1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsFetcherSK1.swift; sourceTree = ""; }; F1A05E9E1B04B32B832DB194 /* PaywallCountdownComponent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PaywallCountdownComponent.swift; sourceTree = ""; }; F516BD28282434070083480B /* StoreKit2StorefrontListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKit2StorefrontListener.swift; sourceTree = ""; }; @@ -4134,6 +4157,7 @@ FD18BF4A2DF0DA5400140FD6 /* MockVirtualCurrencyManager.swift */, FDE57AA62DF892C900101CE2 /* MockVirtualCurrenciesAPI.swift */, 75A0E7912E3D205C00A60BD5 /* MockTestStorePurchaseUI.swift */, + DBAA1FA72F88EAEB000E8C81 /* MockWorkflowsAPI.swift */, ); path = Mocks; sourceTree = ""; @@ -4503,6 +4527,8 @@ FDE57AA12DF88ACA00101CE2 /* VirtualCurrenciesAPI.swift */, 751192DF2E39149200E583CC /* WebBillingAPI.swift */, 1EDB6AA92DC95AB400C771A4 /* WebBillingHTTPRequestPath.swift */, + DB3395DA2F840A790079250C /* Workflows */, + DB3395E02F840AA60079250C /* WorkflowsAPI.swift */, ); path = Networking; sourceTree = ""; @@ -4524,6 +4550,7 @@ 5733B1A327FF9F8300EC2045 /* NetworkErrorTests.swift */, 5733B1A727FFBCC800EC2045 /* BackendErrorTests.swift */, 5733B1A927FFBCF900EC2045 /* BaseErrorTests.swift */, + DB3395E62F840ADA0079250C /* Workflows */, ); path = Networking; sourceTree = ""; @@ -5014,6 +5041,7 @@ 35F38B472C30104E00CD29FD /* BackendGetCustomerCenterConfigTests.swift */, FD5EB26F2DFB19B800DA1974 /* BackendGetVirtualCurrenciesTests.swift */, FD25F3772F33D502007C1A91 /* BackendIsPurchaseAllowedByRestoreBehaviorTests.swift */, + DB3395E22F840ACD0079250C /* BackendGetWorkflowsTests.swift */, ); path = Backend; sourceTree = ""; @@ -5207,6 +5235,7 @@ 57488A7E29CA145B0000EE7E /* ProductEntitlementMappingResponse.swift */, 537B4B2D2DA9662700CEFF4C /* HealthReportResponse.swift */, FDE57A9F2DF8785000101CE2 /* VirtualCurrenciesResponse.swift */, + DB3395D42F840A570079250C /* WorkflowsResponse.swift */, 755C26A32E310B19006DD0AE /* WebBillingProductsResponse.swift */, ); path = Responses; @@ -5952,6 +5981,7 @@ FDED7EC42F33DF0A00827E54 /* IsPurchaseAllowedByRestoreBehaviorCallback.swift */, 57045B3B29C51AF7001A5417 /* ProductEntitlementMappingCallback.swift */, FDE57A9D2DF8783000101CE2 /* VirtualCurrenciesCallback.swift */, + DB3395C92F840A2B0079250C /* WorkflowsCallback.swift */, ); path = Caching; sourceTree = ""; @@ -5980,6 +6010,8 @@ B34605B9279A6E380031CA74 /* PostSubscriberAttributesOperation.swift */, A55D5D65282ECCC100FA7623 /* PostAdServicesTokenOperation.swift */, A56DFDEF286643BF00EF2E32 /* PostAttributionDataOperation.swift */, + DB3395D02F840A400079250C /* GetWorkflowOperation.swift */, + DB3395D12F840A400079250C /* GetWorkflowsOperation.swift */, ); path = Operations; sourceTree = ""; @@ -6076,6 +6108,24 @@ path = Caching; sourceTree = ""; }; + DB3395DA2F840A790079250C /* Workflows */ = { + isa = PBXGroup; + children = ( + DB3395D82F840A790079250C /* WorkflowDetailProcessor.swift */, + DB3395D92F840A790079250C /* WorkflowResponseAction.swift */, + ); + path = Workflows; + sourceTree = ""; + }; + DB3395E62F840ADA0079250C /* Workflows */ = { + isa = PBXGroup; + children = ( + DB3395E42F840ADA0079250C /* WorkflowDetailProcessorTests.swift */, + DB3395E52F840ADA0079250C /* WorkflowResponseTests.swift */, + ); + path = Workflows; + sourceTree = ""; + }; F5714EA626D7A82E00635477 /* CodableExtensions */ = { isa = PBXGroup; children = ( @@ -6806,6 +6856,7 @@ 3543913826F90FE100E669DF /* MockIntroEligibilityCalculator.swift in Sources */, FD2046842CB833CD00166727 /* MockStoreKit2PurchaseIntentListenerDelegate.swift in Sources */, 3543914126F911CC00E669DF /* MockDeviceCache.swift in Sources */, + DBAA1FA82F88EAEB000E8C81 /* MockWorkflowsAPI.swift in Sources */, 3543913C26F9101600E669DF /* MockOperationDispatcher.swift in Sources */, 4FA4C9752A16D49E007D2803 /* MockOfflineEntitlementsManager.swift in Sources */, F5E5E2EE28479BD000216ECD /* ProductsFetcherSK2Tests.swift in Sources */, @@ -6988,6 +7039,7 @@ 5751379527F4C4D80064AB2C /* Optional+Extensions.swift in Sources */, B3852FA026C1ED1F005384F8 /* IdentityManager.swift in Sources */, 9A65E03625918B0500DE00B0 /* ConfigureStrings.swift in Sources */, + DB3395CA2F840A2B0079250C /* WorkflowsCallback.swift in Sources */, 4FF6E4B92B069B8C000141ED /* HTTPRequest+Signing.swift in Sources */, 57488C7729CB90F90000EE7E /* PurchasedProductsFetcher.swift in Sources */, 53E33BBB2E095B8900287158 /* SDKHealthManager.swift in Sources */, @@ -6998,6 +7050,9 @@ 354895D6267BEDE3001DC5B1 /* ReservedSubscriberAttributes.swift in Sources */, 570FAF4B2864EC2300D3C769 /* NonSubscriptionTransaction.swift in Sources */, 2D11F5E1250FF886005A70E8 /* AttributionStrings.swift in Sources */, + DB3395DB2F840A790079250C /* WorkflowDetailProcessor.swift in Sources */, + DB3395E12F840AA60079250C /* WorkflowsAPI.swift in Sources */, + DB3395DD2F840A790079250C /* WorkflowResponseAction.swift in Sources */, 2CD72944268A826F00BFC976 /* Date+Extensions.swift in Sources */, 57069A5428E3918400B86355 /* AsyncExtensions.swift in Sources */, B34605C5279A6E380031CA74 /* CustomerInfoResponseHandler.swift in Sources */, @@ -7088,6 +7143,8 @@ 2D1015DA275959840086173F /* StoreTransaction.swift in Sources */, 4DBF1F362B4D572400D52354 /* LocalReceiptFetcher.swift in Sources */, 1D20E1D62EBCF80E00ABE4CD /* HTTPRequestTimeoutManager.swift in Sources */, + DB3395D22F840A400079250C /* GetWorkflowsOperation.swift in Sources */, + DB3395D32F840A400079250C /* GetWorkflowOperation.swift in Sources */, 57488A7F29CA145B0000EE7E /* ProductEntitlementMappingResponse.swift in Sources */, 88E679472C7503C1007E69D5 /* PaywallStackComponent.swift in Sources */, B34605BC279A6E380031CA74 /* CallbackCache.swift in Sources */, @@ -7187,6 +7244,7 @@ F5714EA826D7A83A00635477 /* Store+Extensions.swift in Sources */, 35F82BAB26A84E130051DF03 /* Dictionary+Extensions.swift in Sources */, 4D2C7D0B2CC40A35002562BC /* PurchaseParams.swift in Sources */, + DB3395D52F840A570079250C /* WorkflowsResponse.swift in Sources */, 9A65E0A02591A23200DE00B0 /* OfferingStrings.swift in Sources */, 5774F9B62805E6CC00997128 /* CustomerInfoResponse.swift in Sources */, 03A98D302D240C41009BCA61 /* UIConfig.swift in Sources */, @@ -7351,6 +7409,7 @@ 2DDF41CB24F6F4C3005BC22D /* ASN1ObjectIdentifierBuilderTests.swift in Sources */, 5766AA5A283D4CAB00FA6091 /* IgnoreHashableTests.swift in Sources */, 0368727A2D9DCF7100506BBB /* DefaultEnumTests.swift in Sources */, + DB3395E32F840ACD0079250C /* BackendGetWorkflowsTests.swift in Sources */, 03C7305B2D35985900297FEC /* TextComponentTests.swift in Sources */, FDE57B0E2DF8BC1100101CE2 /* VirtualCurrenciesDecodingTests.swift in Sources */, 75FCD4CE2E37FBE100036C02 /* SimulatedStoreMockData.swift in Sources */, @@ -7426,6 +7485,8 @@ 75902AFA2F156865005B712A /* MockLocalTransactionMetadataStore.swift in Sources */, 57488B8B29CB756A0000EE7E /* ProductEntitlementMappingTests.swift in Sources */, 1D20E1D82EBCF82900ABE4CD /* HTTPRequestTimeoutManager.swift in Sources */, + DB3395E72F840ADA0079250C /* WorkflowResponseTests.swift in Sources */, + DB3395E82F840ADA0079250C /* WorkflowDetailProcessorTests.swift in Sources */, FD4E63422F34E0B60040BA46 /* PurchasesIsPurchaseAllowedByRestoreBehaviorTests.swift in Sources */, 57ACB12428174B9F000DCC9F /* CustomerInfo+TestExtensions.swift in Sources */, 357349012C3BEB5C000EEB86 /* CustomerCenterConfigDataTests.swift in Sources */, @@ -7464,6 +7525,7 @@ B31C8BEC285BD58F001017B7 /* MockIdentityAPI.swift in Sources */, 351B513D26D4491E00BD2BD7 /* MockDeviceCache.swift in Sources */, 57910CB329C3889B006209D5 /* DispatchTimeIntervalExtensionsTests.swift in Sources */, + DBAA1FA92F88EAEB000E8C81 /* MockWorkflowsAPI.swift in Sources */, 351B515C26D44B7900BD2BD7 /* MockIntroEligibilityCalculator.swift in Sources */, 5733D01128D00354008638D8 /* PromotionalOfferTests.swift in Sources */, 57544C28285FA94B004E54D5 /* MockAttributeSyncing.swift in Sources */, diff --git a/Sources/Networking/Backend.swift b/Sources/Networking/Backend.swift index af93ac1ce5..6e73225649 100644 --- a/Sources/Networking/Backend.swift +++ b/Sources/Networking/Backend.swift @@ -24,6 +24,7 @@ class Backend { let customerCenterConfig: CustomerCenterConfigAPI let redeemWebPurchaseAPI: RedeemWebPurchaseAPI let virtualCurrenciesAPI: VirtualCurrenciesAPI + let workflowsAPI: WorkflowsAPI private let config: BackendConfiguration @@ -65,6 +66,7 @@ class Backend { let customerCenterConfig = CustomerCenterConfigAPI(backendConfig: backendConfig) let redeemWebPurchaseAPI = RedeemWebPurchaseAPI(backendConfig: backendConfig) let virtualCurrenciesAPI = VirtualCurrenciesAPI(backendConfig: backendConfig) + let workflowsAPI = WorkflowsAPI(backendConfig: backendConfig) self.init(backendConfig: backendConfig, customerAPI: customer, @@ -75,7 +77,8 @@ class Backend { internalAPI: internalAPI, customerCenterConfig: customerCenterConfig, redeemWebPurchaseAPI: redeemWebPurchaseAPI, - virtualCurrenciesAPI: virtualCurrenciesAPI) + virtualCurrenciesAPI: virtualCurrenciesAPI, + workflowsAPI: workflowsAPI) } required init(backendConfig: BackendConfiguration, @@ -87,7 +90,8 @@ class Backend { internalAPI: InternalAPI, customerCenterConfig: CustomerCenterConfigAPI, redeemWebPurchaseAPI: RedeemWebPurchaseAPI, - virtualCurrenciesAPI: VirtualCurrenciesAPI) { + virtualCurrenciesAPI: VirtualCurrenciesAPI, + workflowsAPI: WorkflowsAPI) { self.config = backendConfig self.customer = customerAPI @@ -99,6 +103,7 @@ class Backend { self.customerCenterConfig = customerCenterConfig self.redeemWebPurchaseAPI = redeemWebPurchaseAPI self.virtualCurrenciesAPI = virtualCurrenciesAPI + self.workflowsAPI = workflowsAPI } func clearHTTPClientCaches() { diff --git a/Sources/Networking/Caching/WorkflowsCallback.swift b/Sources/Networking/Caching/WorkflowsCallback.swift new file mode 100644 index 0000000000..19e2ae32cf --- /dev/null +++ b/Sources/Networking/Caching/WorkflowsCallback.swift @@ -0,0 +1,28 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowsCallback.swift +// +// Created by RevenueCat. + +import Foundation + +struct WorkflowsListCallback: CacheKeyProviding { + + let cacheKey: String + let completion: (Result) -> Void + +} + +struct WorkflowDetailCallback: CacheKeyProviding { + + let cacheKey: String + let completion: (Result) -> Void + +} diff --git a/Sources/Networking/HTTPClient/HTTPClient.swift b/Sources/Networking/HTTPClient/HTTPClient.swift index f1795abee5..197dc6e90e 100644 --- a/Sources/Networking/HTTPClient/HTTPClient.swift +++ b/Sources/Networking/HTTPClient/HTTPClient.swift @@ -219,6 +219,31 @@ extension HTTPClient { // - Class is not `final` (it's mocked). This implicitly makes subclasses `Sendable` even if they're not thread-safe. extension HTTPClient: @unchecked Sendable {} +// MARK: - CDN + +internal extension HTTPClient { + + /// Fetches raw data from an arbitrary URL using the client's configured `URLSession`. + /// + /// Use this for CDN or other non-RC-API requests where the SDK's path-based request building + /// is not applicable, but we still want the same session configuration (timeouts, connection limits). + func fetchRawData(from url: URL, completion: @escaping (Result) -> Void) { + self.session.dataTask(with: url) { data, response, error in + if let error = error { + completion(.failure(error)) + } else if let httpResponse = response as? HTTPURLResponse, + !(200..<300).contains(httpResponse.statusCode) { + completion(.failure(URLError(.badServerResponse))) + } else if let data = data { + completion(.success(data)) + } else { + completion(.failure(URLError(.unknown))) + } + }.resume() + } + +} + // MARK: - Private internal extension HTTPClient { diff --git a/Sources/Networking/HTTPClient/HTTPRequestPath.swift b/Sources/Networking/HTTPClient/HTTPRequestPath.swift index fb6108eba4..fa5a6fff37 100644 --- a/Sources/Networking/HTTPClient/HTTPRequestPath.swift +++ b/Sources/Networking/HTTPClient/HTTPRequestPath.swift @@ -11,6 +11,8 @@ // // Created by Nacho Soto on 8/8/23. +// swiftlint:disable file_length + import Foundation protocol HTTPRequestPath { @@ -101,6 +103,8 @@ extension HTTPRequest { case getProductEntitlementMapping case getCustomerCenterConfig(appUserID: String) case getVirtualCurrencies(appUserID: String) + case getWorkflows(appUserID: String) + case getWorkflow(appUserID: String, workflowId: String) case postRedeemWebPurchase case postCreateTicket case isPurchaseAllowedByRestoreBehavior(appUserID: String) @@ -187,6 +191,8 @@ extension HTTPRequest.Path: HTTPRequestPath { .getProductEntitlementMapping, .getCustomerCenterConfig, .getVirtualCurrencies, + .getWorkflows, + .getWorkflow, .appHealthReport, .postCreateTicket, .isPurchaseAllowedByRestoreBehavior: @@ -213,6 +219,8 @@ extension HTTPRequest.Path: HTTPRequestPath { .getProductEntitlementMapping, .getCustomerCenterConfig, .getVirtualCurrencies, + .getWorkflows, + .getWorkflow, .appHealthReport, .postCreateTicket, .isPurchaseAllowedByRestoreBehavior: @@ -232,6 +240,7 @@ extension HTTPRequest.Path: HTTPRequestPath { .getOfferings, .getProductEntitlementMapping, .getVirtualCurrencies, + .getWorkflows, .appHealthReport, .appHealthReportAvailability, .isPurchaseAllowedByRestoreBehavior: @@ -243,6 +252,7 @@ extension HTTPRequest.Path: HTTPRequestPath { .postOfferForSigning, .postRedeemWebPurchase, .getCustomerCenterConfig, + .getWorkflow, .postCreateTicket: return false } @@ -267,6 +277,8 @@ extension HTTPRequest.Path: HTTPRequestPath { .postRedeemWebPurchase, .getProductEntitlementMapping, .getCustomerCenterConfig, + .getWorkflows, + .getWorkflow, .appHealthReport, .postCreateTicket: return false @@ -327,6 +339,12 @@ extension HTTPRequest.Path: HTTPRequestPath { case let .getVirtualCurrencies(appUserID): return "subscribers/\(Self.escape(appUserID))/virtual_currencies" + case let .getWorkflows(appUserID): + return "subscribers/\(Self.escape(appUserID))/workflows" + + case let .getWorkflow(appUserID, workflowId): + return "subscribers/\(Self.escape(appUserID))/workflows/\(Self.escape(workflowId))" + case .postCreateTicket: return "customercenter/support/create-ticket" case let .isPurchaseAllowedByRestoreBehavior(appUserID): @@ -381,6 +399,12 @@ extension HTTPRequest.Path: HTTPRequestPath { case .getVirtualCurrencies: return "get_virtual_currencies" + case .getWorkflows: + return "get_workflows" + + case .getWorkflow: + return "get_workflow" + case .appHealthReportAvailability: return "get_app_health_report_availability" diff --git a/Sources/Networking/Operations/GetWorkflowOperation.swift b/Sources/Networking/Operations/GetWorkflowOperation.swift new file mode 100644 index 0000000000..0a953f38bf --- /dev/null +++ b/Sources/Networking/Operations/GetWorkflowOperation.swift @@ -0,0 +1,132 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// GetWorkflowOperation.swift +// +// Created by RevenueCat. + +import Foundation + +final class GetWorkflowOperation: CacheableNetworkOperation { + + private let workflowDetailCallbackCache: CallbackCache + private let configuration: AppUserConfiguration + private let workflowId: String + private let detailProcessor: WorkflowDetailProcessor + + static func createFactory( + configuration: UserSpecificConfiguration, + workflowId: String, + detailProcessor: WorkflowDetailProcessor, + workflowDetailCallbackCache: CallbackCache + ) -> CacheableNetworkOperationFactory { + return .init({ cacheKey in + .init( + configuration: configuration, + workflowId: workflowId, + detailProcessor: detailProcessor, + workflowDetailCallbackCache: workflowDetailCallbackCache, + cacheKey: cacheKey + ) + }, + individualizedCacheKeyPart: configuration.appUserID + "\n" + workflowId) + } + + private init(configuration: UserSpecificConfiguration, + workflowId: String, + detailProcessor: WorkflowDetailProcessor, + workflowDetailCallbackCache: CallbackCache, + cacheKey: String) { + self.configuration = configuration + self.workflowId = workflowId + self.detailProcessor = detailProcessor + self.workflowDetailCallbackCache = workflowDetailCallbackCache + + super.init(configuration: configuration, cacheKey: cacheKey) + } + + override func begin(completion: @escaping () -> Void) { + self.getWorkflow(completion: completion) + } + +} + +// Restating inherited @unchecked Sendable from Foundation's Operation +extension GetWorkflowOperation: @unchecked Sendable {} + +private extension GetWorkflowOperation { + + func getWorkflow(completion: @escaping () -> Void) { + let appUserID = self.configuration.appUserID + + guard appUserID.isNotEmpty else { + self.workflowDetailCallbackCache.performOnAllItemsAndRemoveFromCache(withCacheable: self) { callback in + callback.completion(.failure(.missingAppUserID())) + } + completion() + return + } + + let request = HTTPRequest( + method: .get, + path: .getWorkflow(appUserID: appUserID, workflowId: self.workflowId) + ) + + httpClient.perform(request) { (response: VerifiedHTTPResponse.Result) in + self.handleResponse(response, completion: completion) + } + } + + func handleResponse(_ response: VerifiedHTTPResponse.Result, completion: @escaping () -> Void) { + switch response { + case .failure(let networkError): + defer { completion() } + self.distribute(.failure(BackendError.networkError(networkError))) + + case .success(let verifiedResponse): + self.detailProcessor.process(verifiedResponse.body) { processingResult in + defer { completion() } + self.distribute(self.backendResult(from: processingResult, envelopeData: verifiedResponse.body)) + } + } + } + + func backendResult( + from processingResult: Result, + envelopeData: Data + ) -> Result { + switch processingResult { + case .success(let processed): + do { + let workflow = try PublishedWorkflow.create(with: processed.workflowData) + return .success(WorkflowFetchResult(workflow: workflow, enrolledVariants: processed.enrolledVariants)) + } catch { + return .failure(BackendError.networkError(NetworkError.decoding(error, processed.workflowData))) + } + case .failure(let processingError as WorkflowDetailProcessingError): + switch processingError { + case .cdnFetchFailed(let underlyingError): + return .failure(.networkError(NetworkError.networkError(underlyingError))) + case .invalidEnvelopeJson, .unknownAction, .missingInlineData, .missingCdnUrl: + return .failure(.networkError(NetworkError.decoding(processingError, envelopeData))) + } + case .failure(let error): + return .failure(.networkError(NetworkError.decoding(error, envelopeData))) + } + } + + func distribute(_ result: Result) { + self.workflowDetailCallbackCache.performOnAllItemsAndRemoveFromCache( + withCacheable: self + ) { callbackObject in + callbackObject.completion(result) + } + } + +} diff --git a/Sources/Networking/Operations/GetWorkflowsOperation.swift b/Sources/Networking/Operations/GetWorkflowsOperation.swift new file mode 100644 index 0000000000..fe1ab7babe --- /dev/null +++ b/Sources/Networking/Operations/GetWorkflowsOperation.swift @@ -0,0 +1,84 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// GetWorkflowsOperation.swift +// +// Created by RevenueCat. + +import Foundation + +final class GetWorkflowsOperation: CacheableNetworkOperation { + + private let workflowsCallbackCache: CallbackCache + private let configuration: AppUserConfiguration + + static func createFactory( + configuration: UserSpecificConfiguration, + workflowsCallbackCache: CallbackCache + ) -> CacheableNetworkOperationFactory { + return .init({ cacheKey in + .init( + configuration: configuration, + workflowsCallbackCache: workflowsCallbackCache, + cacheKey: cacheKey + ) + }, + individualizedCacheKeyPart: configuration.appUserID) + } + + private init(configuration: UserSpecificConfiguration, + workflowsCallbackCache: CallbackCache, + cacheKey: String) { + self.configuration = configuration + self.workflowsCallbackCache = workflowsCallbackCache + + super.init(configuration: configuration, cacheKey: cacheKey) + } + + override func begin(completion: @escaping () -> Void) { + self.getWorkflows(completion: completion) + } + +} + +// Restating inherited @unchecked Sendable from Foundation's Operation +extension GetWorkflowsOperation: @unchecked Sendable {} + +private extension GetWorkflowsOperation { + + func getWorkflows(completion: @escaping () -> Void) { + let appUserID = self.configuration.appUserID + + guard appUserID.isNotEmpty else { + self.workflowsCallbackCache.performOnAllItemsAndRemoveFromCache(withCacheable: self) { callback in + callback.completion(.failure(.missingAppUserID())) + } + completion() + return + } + + let request = HTTPRequest(method: .get, path: .getWorkflows(appUserID: appUserID)) + + httpClient.perform(request) { (response: VerifiedHTTPResponse.Result) in + defer { + completion() + } + + self.workflowsCallbackCache.performOnAllItemsAndRemoveFromCache( + withCacheable: self + ) { callbackObject in + callbackObject.completion(response + .map { $0.body } + .mapError(BackendError.networkError) + ) + } + } + } + +} diff --git a/Sources/Networking/Responses/WorkflowsResponse.swift b/Sources/Networking/Responses/WorkflowsResponse.swift new file mode 100644 index 0000000000..6546fdf3b4 --- /dev/null +++ b/Sources/Networking/Responses/WorkflowsResponse.swift @@ -0,0 +1,132 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowsResponse.swift +// +// Created by RevenueCat. + +import Foundation + +// MARK: - List response + +struct WorkflowSummary { + + let id: String + let displayName: String + +} + +struct WorkflowsListResponse { + + let workflows: [WorkflowSummary] + let uiConfig: UIConfig + +} + +// MARK: - Detail models + +struct WorkflowTrigger { + + let name: String? + let type: String + let actionId: String? + let componentId: String? + +} + +struct WorkflowTriggerAction { + + let type: String + let stepId: String? + +} + +struct WorkflowStep { + + let id: String + let type: String + let screenId: String? + @DefaultDecodable.EmptyDictionary + var paramValues: [String: AnyDecodable] + @DefaultDecodable.EmptyArray + var triggers: [WorkflowTrigger] + @DefaultDecodable.EmptyDictionary + var outputs: [String: AnyDecodable] + @DefaultDecodable.EmptyDictionary + var triggerActions: [String: WorkflowTriggerAction] + let metadata: [String: AnyDecodable]? + +} + +struct WorkflowScreen { + + let name: String? + let templateName: String + @DefaultDecodable.Zero + var revision: Int + let assetBaseURL: URL + let componentsConfig: PaywallComponentsData.ComponentsConfig + let componentsLocalizations: [PaywallComponent.LocaleID: PaywallComponent.LocalizationDictionary] + let defaultLocale: PaywallComponent.LocaleID + @DefaultDecodable.EmptyDictionary + var config: [String: AnyDecodable] + let offeringId: String? + +} + +struct PublishedWorkflow { + + let id: String + let displayName: String + let initialStepId: String + let steps: [String: WorkflowStep] + let screens: [String: WorkflowScreen] + let uiConfig: UIConfig + let contentMaxWidth: Int? + let metadata: [String: AnyDecodable]? + +} + +struct WorkflowFetchResult { + + let workflow: PublishedWorkflow + let enrolledVariants: [String: String]? + +} + +// MARK: - Codable + +extension WorkflowSummary: Codable, Equatable, Sendable {} +extension WorkflowsListResponse: Codable, Equatable, Sendable {} + +extension WorkflowTrigger: Codable, Equatable, Sendable {} +extension WorkflowTriggerAction: Codable, Equatable, Sendable {} +extension WorkflowStep: Codable, Equatable, Sendable {} + +extension WorkflowScreen: Codable, Equatable, Sendable { + + private enum CodingKeys: String, CodingKey { + case name + case templateName + case revision + case assetBaseURL = "assetBaseUrl" + case componentsConfig + case componentsLocalizations + case defaultLocale + case config + case offeringId + } + +} + +extension PublishedWorkflow: Codable, Equatable, Sendable {} +extension WorkflowFetchResult: Equatable, Sendable {} + +extension WorkflowsListResponse: HTTPResponseBody {} +extension PublishedWorkflow: HTTPResponseBody {} diff --git a/Sources/Networking/Workflows/WorkflowDetailProcessor.swift b/Sources/Networking/Workflows/WorkflowDetailProcessor.swift new file mode 100644 index 0000000000..7fbe85b8d3 --- /dev/null +++ b/Sources/Networking/Workflows/WorkflowDetailProcessor.swift @@ -0,0 +1,103 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowDetailProcessor.swift +// +// Created by RevenueCat. + +import Foundation + +/// A closure that fetches compiled workflow JSON from a CDN URL. +/// +/// - Parameters: +/// - cdnUrl: The CDN URL string to fetch from. +/// - completion: Called with the raw `Data` on success, or an `Error` on failure. +typealias WorkflowCdnFetch = @Sendable (String, @escaping (Result) -> Void) -> Void + +/// Typed errors thrown by `WorkflowDetailProcessor` so callers can distinguish failure modes. +enum WorkflowDetailProcessingError: Error { + + case cdnFetchFailed(Error) + case invalidEnvelopeJson + case unknownAction(String) + case missingInlineData + case missingCdnUrl + +} + +struct WorkflowDetailProcessingResult { + + let workflowData: Data + let enrolledVariants: [String: String]? + +} + +/// Normalizes a successful workflow-detail HTTP payload: +/// `inline` (unwraps `data`) or `use_cdn` (fetches JSON from CDN). +final class WorkflowDetailProcessor: Sendable { + + private let cdnFetch: WorkflowCdnFetch + + init(cdnFetch: @escaping WorkflowCdnFetch) { + self.cdnFetch = cdnFetch + } + + func process(_ data: Data, completion: @escaping (Result) -> Void) { + let json: [String: Any]? + do { + json = try JSONSerialization.jsonObject(with: data) as? [String: Any] + } catch { + completion(.failure(WorkflowDetailProcessingError.invalidEnvelopeJson)) + return + } + + guard let json else { + completion(.failure(WorkflowDetailProcessingError.invalidEnvelopeJson)) + return + } + + let enrolledVariants = json["enrolled_variants"] as? [String: String] + + guard let actionString = json["action"] as? String, + let action = WorkflowResponseAction(rawValue: actionString) else { + let actionValue = json["action"] as? String ?? "nil" + completion(.failure(WorkflowDetailProcessingError.unknownAction(actionValue))) + return + } + + switch action { + case .inline: + guard let inlineData = json["data"] else { + completion(.failure(WorkflowDetailProcessingError.missingInlineData)) + return + } + do { + let workflowData = try JSONSerialization.data(withJSONObject: inlineData) + completion(.success(.init(workflowData: workflowData, enrolledVariants: enrolledVariants))) + } catch { + completion(.failure(error)) + } + + case .useCdn: + guard let cdnUrl = json["url"] as? String else { + completion(.failure(WorkflowDetailProcessingError.missingCdnUrl)) + return + } + self.cdnFetch(cdnUrl) { result in + switch result { + case .success(let workflowData): + completion(.success(.init(workflowData: workflowData, enrolledVariants: enrolledVariants))) + case .failure(let error): + completion(.failure(WorkflowDetailProcessingError.cdnFetchFailed(error))) + } + } + } + } + +} diff --git a/Sources/Networking/Workflows/WorkflowResponseAction.swift b/Sources/Networking/Workflows/WorkflowResponseAction.swift new file mode 100644 index 0000000000..68a697fac1 --- /dev/null +++ b/Sources/Networking/Workflows/WorkflowResponseAction.swift @@ -0,0 +1,19 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowResponseAction.swift +// +// Created by RevenueCat. + +import Foundation + +enum WorkflowResponseAction: String { + case inline + case useCdn = "use_cdn" +} diff --git a/Sources/Networking/WorkflowsAPI.swift b/Sources/Networking/WorkflowsAPI.swift new file mode 100644 index 0000000000..3d8f288216 --- /dev/null +++ b/Sources/Networking/WorkflowsAPI.swift @@ -0,0 +1,93 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowsAPI.swift +// +// Created by RevenueCat. + +import Foundation + +class WorkflowsAPI { + + typealias WorkflowsListResponseHandler = Backend.ResponseHandler + typealias WorkflowDetailResponseHandler = Backend.ResponseHandler + + private let workflowsListCallbackCache: CallbackCache + private let workflowDetailCallbackCache: CallbackCache + private let backendConfig: BackendConfiguration + private let detailProcessor: WorkflowDetailProcessor + + init(backendConfig: BackendConfiguration, + cdnFetch: WorkflowCdnFetch? = nil) { + self.backendConfig = backendConfig + self.workflowsListCallbackCache = .init() + self.workflowDetailCallbackCache = .init() + self.detailProcessor = WorkflowDetailProcessor( + cdnFetch: cdnFetch ?? Self.defaultCdnFetch(httpClient: backendConfig.httpClient) + ) + } + + private static func defaultCdnFetch(httpClient: HTTPClient) -> WorkflowCdnFetch { + return { cdnUrl, completion in + guard let url = URL(string: cdnUrl) else { + completion(.failure(URLError(.badURL))) + return + } + httpClient.fetchRawData(from: url, completion: completion) + } + } + + func getWorkflows(appUserID: String, + isAppBackgrounded: Bool, + completion: @escaping WorkflowsListResponseHandler) { + let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient, + appUserID: appUserID) + let factory = GetWorkflowsOperation.createFactory( + configuration: config, + workflowsCallbackCache: self.workflowsListCallbackCache + ) + + let callback = WorkflowsListCallback(cacheKey: factory.cacheKey, completion: completion) + let cacheStatus = self.workflowsListCallbackCache.add(callback) + + self.backendConfig.addCacheableOperation( + with: factory, + delay: .default(forBackgroundedApp: isAppBackgrounded), + cacheStatus: cacheStatus + ) + } + + func getWorkflow(appUserID: String, + workflowId: String, + isAppBackgrounded: Bool, + completion: @escaping WorkflowDetailResponseHandler) { + let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient, + appUserID: appUserID) + let factory = GetWorkflowOperation.createFactory( + configuration: config, + workflowId: workflowId, + detailProcessor: self.detailProcessor, + workflowDetailCallbackCache: self.workflowDetailCallbackCache + ) + + let callback = WorkflowDetailCallback(cacheKey: factory.cacheKey, completion: completion) + let cacheStatus = self.workflowDetailCallbackCache.add(callback) + + self.backendConfig.addCacheableOperation( + with: factory, + delay: .default(forBackgroundedApp: isAppBackgrounded), + cacheStatus: cacheStatus + ) + } + +} + +// @unchecked because: +// - Class is not `final` (it's mocked). This implicitly makes subclasses `Sendable` even if they're not thread-safe. +extension WorkflowsAPI: @unchecked Sendable {} diff --git a/Tests/UnitTests/Mocks/MockBackend.swift b/Tests/UnitTests/Mocks/MockBackend.swift index 10899ec083..8e0656d681 100644 --- a/Tests/UnitTests/Mocks/MockBackend.swift +++ b/Tests/UnitTests/Mocks/MockBackend.swift @@ -47,6 +47,7 @@ class MockBackend: Backend { let customerCenterConfig = CustomerCenterConfigAPI(backendConfig: backendConfig) let redeemWebPurchaseAPI = MockRedeemWebPurchaseAPI() let virtualCurrenciesAPI = MockVirtualCurrenciesAPI() + let workflowsAPI = MockWorkflowsAPI() self.init(backendConfig: backendConfig, customerAPI: customer, @@ -57,7 +58,8 @@ class MockBackend: Backend { internalAPI: internalAPI, customerCenterConfig: customerCenterConfig, redeemWebPurchaseAPI: redeemWebPurchaseAPI, - virtualCurrenciesAPI: virtualCurrenciesAPI) + virtualCurrenciesAPI: virtualCurrenciesAPI, + workflowsAPI: workflowsAPI) } override func post(receipt: EncodedAppleReceipt, diff --git a/Tests/UnitTests/Mocks/MockWorkflowsAPI.swift b/Tests/UnitTests/Mocks/MockWorkflowsAPI.swift new file mode 100644 index 0000000000..e9c396b46d --- /dev/null +++ b/Tests/UnitTests/Mocks/MockWorkflowsAPI.swift @@ -0,0 +1,54 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// MockWorkflowsAPI.swift +// +// Created by RevenueCat. + +import Foundation +@testable import RevenueCat + +class MockWorkflowsAPI: WorkflowsAPI { + + init() { + super.init(backendConfig: MockBackendConfiguration()) + } + + var invokedGetWorkflows = false + var invokedGetWorkflowsCount = 0 + var invokedGetWorkflowsParameters: (appUserID: String, isAppBackgrounded: Bool)? + var stubbedGetWorkflowsResult: Result? + + override func getWorkflows(appUserID: String, + isAppBackgrounded: Bool, + completion: @escaping WorkflowsListResponseHandler) { + self.invokedGetWorkflows = true + self.invokedGetWorkflowsCount += 1 + self.invokedGetWorkflowsParameters = (appUserID, isAppBackgrounded) + + completion(self.stubbedGetWorkflowsResult ?? .failure(.missingAppUserID())) + } + + var invokedGetWorkflow = false + var invokedGetWorkflowCount = 0 + var invokedGetWorkflowParameters: (appUserID: String, workflowId: String, isAppBackgrounded: Bool)? + var stubbedGetWorkflowResult: Result? + + override func getWorkflow(appUserID: String, + workflowId: String, + isAppBackgrounded: Bool, + completion: @escaping WorkflowDetailResponseHandler) { + self.invokedGetWorkflow = true + self.invokedGetWorkflowCount += 1 + self.invokedGetWorkflowParameters = (appUserID, workflowId, isAppBackgrounded) + + completion(self.stubbedGetWorkflowResult ?? .failure(.missingAppUserID())) + } + +} diff --git a/Tests/UnitTests/Networking/Backend/BackendGetWorkflowsTests.swift b/Tests/UnitTests/Networking/Backend/BackendGetWorkflowsTests.swift new file mode 100644 index 0000000000..51b240661b --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/BackendGetWorkflowsTests.swift @@ -0,0 +1,350 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// BackendGetWorkflowsTests.swift +// +// Created by RevenueCat. + +import Foundation +import Nimble +import XCTest + +@testable import RevenueCat + +class BackendGetWorkflowsTests: BaseBackendTests { + + override func createClient() -> MockHTTPClient { + super.createClient(#file) + } + + func testGetWorkflowsCallsHTTPMethod() { + self.httpClient.mock( + requestPath: .getWorkflows(appUserID: Self.userID), + response: .init(statusCode: .success, response: Self.emptyWorkflowsResponse) + ) + + let result = waitUntilValue { completed in + self.workflowsAPI.getWorkflows( + appUserID: Self.userID, + isAppBackgrounded: false, + completion: completed + ) + } + + expect(result).to(beSuccess()) + expect(self.httpClient.calls).to(haveCount(1)) + } + + func testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded() { + self.httpClient.mock( + requestPath: .getWorkflows(appUserID: Self.userID), + response: .init(statusCode: .success, response: Self.emptyWorkflowsResponse) + ) + + let result = waitUntilValue { completed in + self.workflowsAPI.getWorkflows( + appUserID: Self.userID, + isAppBackgrounded: true, + completion: completed + ) + } + + expect(result).to(beSuccess()) + expect(self.httpClient.calls).to(haveCount(1)) + expect(self.operationDispatcher.invokedDispatchOnWorkerThreadDelayParam) == .default + } + + func testGetWorkflowsCachesForSameUserID() { + self.httpClient.mock( + requestPath: .getWorkflows(appUserID: Self.userID), + response: .init(statusCode: .success, + response: Self.emptyWorkflowsResponse, + delay: .milliseconds(10)) + ) + self.workflowsAPI.getWorkflows(appUserID: Self.userID, isAppBackgrounded: false) { _ in } + self.workflowsAPI.getWorkflows(appUserID: Self.userID, isAppBackgrounded: false) { _ in } + + expect(self.httpClient.calls).toEventually(haveCount(1)) + } + + func testGetWorkflowsReturnsWorkflows() throws { + self.httpClient.mock( + requestPath: .getWorkflows(appUserID: Self.userID), + response: .init(statusCode: .success, response: Self.oneWorkflowResponse) + ) + + let result: Atomic?> = nil + self.workflowsAPI.getWorkflows(appUserID: Self.userID, isAppBackgrounded: false) { + result.value = $0 + } + + expect(result.value).toEventuallyNot(beNil()) + + let response = try XCTUnwrap(result.value?.value) + expect(response.workflows).to(haveCount(1)) + expect(response.workflows.first?.id) == "wf_1" + expect(response.workflows.first?.displayName) == "Flow A" + } + + func testGetWorkflowsNetworkErrorSendsError() { + let mockedError: NetworkError = .unexpectedResponse(nil) + + self.httpClient.mock( + requestPath: .getWorkflows(appUserID: Self.userID), + response: .init(error: mockedError) + ) + + let result = waitUntilValue { completed in + self.workflowsAPI.getWorkflows( + appUserID: Self.userID, + isAppBackgrounded: false, + completion: completed + ) + } + + expect(result).to(beFailure()) + expect(result?.error) == .networkError(mockedError) + } + + func testGetWorkflowsSkipsBackendCallIfAppUserIDIsEmpty() { + waitUntil { completed in + self.workflowsAPI.getWorkflows(appUserID: "", isAppBackgrounded: false) { _ in + completed() + } + } + + expect(self.httpClient.calls).to(beEmpty()) + } + + func testGetWorkflowsCallsCompletionWithErrorIfAppUserIDIsEmpty() { + let receivedError = waitUntilValue { completed in + self.workflowsAPI.getWorkflows(appUserID: "", isAppBackgrounded: false) { result in + completed(result.error) + } + } + + expect(receivedError) == .missingAppUserID() + } + +} + +// MARK: - GetWorkflow tests + +class BackendGetWorkflowTests: BaseBackendTests { + + override func createClient() -> MockHTTPClient { + super.createClient(#file) + } + + func testGetWorkflowInlineUnwrapsData() throws { + self.httpClient.mock( + requestPath: .getWorkflow(appUserID: Self.userID, workflowId: "wf_1"), + response: .init(statusCode: .success, response: Self.inlineEnvelopeResponse) + ) + + let result: Atomic?> = nil + self.workflowsAPI.getWorkflow( + appUserID: Self.userID, + workflowId: "wf_1", + isAppBackgrounded: false + ) { + result.value = $0 + } + + expect(result.value).toEventuallyNot(beNil()) + + let fetchResult = try XCTUnwrap(result.value?.value) + expect(fetchResult.workflow.id) == "wf_1" + expect(fetchResult.workflow.displayName) == "Test Workflow" + expect(fetchResult.workflow.initialStepId) == "step_1" + expect(fetchResult.enrolledVariants).to(beNil()) + } + + func testGetWorkflowInlineWithEnrolledVariants() throws { + self.httpClient.mock( + requestPath: .getWorkflow(appUserID: Self.userID, workflowId: "wf_1"), + response: .init(statusCode: .success, response: Self.inlineEnvelopeWithVariantsResponse) + ) + + let result: Atomic?> = nil + self.workflowsAPI.getWorkflow( + appUserID: Self.userID, + workflowId: "wf_1", + isAppBackgrounded: false + ) { + result.value = $0 + } + + expect(result.value).toEventuallyNot(beNil()) + + let fetchResult = try XCTUnwrap(result.value?.value) + expect(fetchResult.workflow.id) == "wf_1" + expect(fetchResult.enrolledVariants) == ["experiment_1": "variant_a"] + } + + func testGetWorkflowPropagatesHTTPErrors() { + self.httpClient.mock( + requestPath: .getWorkflow(appUserID: Self.userID, workflowId: "wf_missing"), + response: .init(statusCode: .notFoundError, response: ["error": "not found"] as [String: Any]) + ) + + let result = waitUntilValue { completed in + self.workflowsAPI.getWorkflow( + appUserID: Self.userID, + workflowId: "wf_missing", + isAppBackgrounded: false, + completion: completed + ) + } + + expect(result).to(beFailure()) + } + + func testGetWorkflowCachesForSameUserIDAndWorkflowId() { + self.httpClient.mock( + requestPath: .getWorkflow(appUserID: Self.userID, workflowId: "wf_1"), + response: .init(statusCode: .success, + response: Self.inlineEnvelopeResponse, + delay: .milliseconds(10)) + ) + + self.workflowsAPI.getWorkflow( + appUserID: Self.userID, + workflowId: "wf_1", + isAppBackgrounded: false + ) { _ in } + self.workflowsAPI.getWorkflow( + appUserID: Self.userID, + workflowId: "wf_1", + isAppBackgrounded: false + ) { _ in } + + expect(self.httpClient.calls).toEventually(haveCount(1)) + } + + func testGetWorkflowUseCdnFetchesWorkflowFromCdnUrl() throws { + let cdnWorkflowData = try JSONSerialization.data(withJSONObject: Self.minimalWorkflowData) + self.stubbedCdnFetch = { _, completion in completion(.success(cdnWorkflowData)) } + + self.httpClient.mock( + requestPath: .getWorkflow(appUserID: Self.userID, workflowId: "wf_1"), + response: .init(statusCode: .success, response: Self.cdnEnvelopeResponse) + ) + + let result = waitUntilValue { completed in + self.workflowsAPI.getWorkflow( + appUserID: Self.userID, + workflowId: "wf_1", + isAppBackgrounded: false, + completion: completed + ) + } + + expect(result).to(beSuccess { fetchResult in + expect(fetchResult.workflow.id) == "wf_1" + expect(fetchResult.workflow.displayName) == "Test Workflow" + }) + } + + func testGetWorkflowSkipsBackendCallIfAppUserIDIsEmpty() { + waitUntil { completed in + self.workflowsAPI.getWorkflow( + appUserID: "", + workflowId: "wf_1", + isAppBackgrounded: false + ) { _ in + completed() + } + } + + expect(self.httpClient.calls).to(beEmpty()) + } + +} + +// MARK: - Test data + +private extension BackendGetWorkflowsTests { + + static let minimalUiConfig: [String: Any] = [ + "app": [ + "colors": [:] as [String: Any], + "fonts": [:] as [String: Any] + ] as [String: Any], + "localizations": [:] as [String: Any], + "variable_config": [ + "variable_compatibility_map": [:] as [String: String], + "function_compatibility_map": [:] as [String: String] + ] as [String: Any] + ] + + static let emptyWorkflowsResponse: [String: Any] = [ + "workflows": [] as [Any], + "ui_config": minimalUiConfig + ] + + static let oneWorkflowResponse: [String: Any] = [ + "workflows": [ + [ + "id": "wf_1", + "display_name": "Flow A" + ] as [String: Any] + ], + "ui_config": minimalUiConfig + ] + +} + +private extension BackendGetWorkflowTests { + + static let minimalUiConfig: [String: Any] = [ + "app": [ + "colors": [:] as [String: Any], + "fonts": [:] as [String: Any] + ] as [String: Any], + "localizations": [:] as [String: Any], + "variable_config": [ + "variable_compatibility_map": [:] as [String: String], + "function_compatibility_map": [:] as [String: String] + ] as [String: Any] + ] + + static let minimalWorkflowData: [String: Any] = [ + "id": "wf_1", + "display_name": "Test Workflow", + "initial_step_id": "step_1", + "steps": [ + "step_1": [ + "id": "step_1", + "type": "screen" + ] as [String: Any] + ] as [String: Any], + "screens": [:] as [String: Any], + "ui_config": minimalUiConfig + ] + + static let inlineEnvelopeResponse: [String: Any] = [ + "action": "inline", + "data": minimalWorkflowData + ] + + static let inlineEnvelopeWithVariantsResponse: [String: Any] = [ + "action": "inline", + "data": minimalWorkflowData, + "enrolled_variants": [ + "experiment_1": "variant_a" + ] as [String: String] + ] + + static let cdnEnvelopeResponse: [String: Any] = [ + "action": "use_cdn", + "url": "https://cdn.example/wf.json" + ] + +} diff --git a/Tests/UnitTests/Networking/Backend/BaseBackendTest.swift b/Tests/UnitTests/Networking/Backend/BaseBackendTest.swift index e5fc8d7dfb..c3832c9e31 100644 --- a/Tests/UnitTests/Networking/Backend/BaseBackendTest.swift +++ b/Tests/UnitTests/Networking/Backend/BaseBackendTest.swift @@ -36,6 +36,10 @@ class BaseBackendTests: TestCase { private(set) var customerCenterConfig: CustomerCenterConfigAPI! private(set) var redeemWebPurchaseAPI: RedeemWebPurchaseAPI! private(set) var virtualCurrenciesAPI: VirtualCurrenciesAPI! + private(set) var workflowsAPI: WorkflowsAPI! + /// Controls what the CDN fetch returns. Tests can reassign this before triggering a `use_cdn` response + /// because the closure registered with `WorkflowsAPI` captures `self` and reads this property at call time. + var stubbedCdnFetch: WorkflowCdnFetch = { _, completion in completion(.success(Data())) } static let apiKey = "asharedsecret" static let userID = "user" @@ -92,6 +96,9 @@ class BaseBackendTests: TestCase { self.customerCenterConfig = CustomerCenterConfigAPI(backendConfig: backendConfig) self.redeemWebPurchaseAPI = RedeemWebPurchaseAPI(backendConfig: backendConfig) self.virtualCurrenciesAPI = VirtualCurrenciesAPI(backendConfig: backendConfig) + self.workflowsAPI = WorkflowsAPI(backendConfig: backendConfig, cdnFetch: { [weak self] cdnUrl, completion in + self?.stubbedCdnFetch(cdnUrl, completion) ?? completion(.success(Data())) + }) self.backend = Backend(backendConfig: backendConfig, customerAPI: customer, @@ -102,7 +109,8 @@ class BaseBackendTests: TestCase { internalAPI: self.internalAPI, customerCenterConfig: self.customerCenterConfig, redeemWebPurchaseAPI: self.redeemWebPurchaseAPI, - virtualCurrenciesAPI: self.virtualCurrenciesAPI) + virtualCurrenciesAPI: self.virtualCurrenciesAPI, + workflowsAPI: self.workflowsAPI) } var verificationMode: Configuration.EntitlementVerificationMode { diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..9979ad3824 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..9979ad3824 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..9979ad3824 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..d277e5d995 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS16-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..9979ad3824 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..9979ad3824 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..9979ad3824 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..d277e5d995 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..c4bcf00734 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS17-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "content-type" : "application/json", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-Storefront" : "USA", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Version" : "4.0.0" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..fc60b3e8fe --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS18-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..fc60b3e8fe --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/iOS26-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..bef852c9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..bef852c9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..bef852c9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..8061954148 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..fbb355f0dc --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..fbb355f0dc --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..fbb355f0dc --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..fbb355f0dc --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..fbb355f0dc --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/macOS-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,29 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "false", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..914bd2b9d8 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..fc60b3e8fe --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..f033aa5118 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/tvOS18-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "2", + "X-StoreKit2-Enabled" : "true", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json new file mode 100644 index 0000000000..de46bebfdf --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowCachesForSameUserIDAndWorkflowId.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowInlineUnwrapsData.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowInlineUnwrapsData.1.json new file mode 100644 index 0000000000..de46bebfdf --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowInlineUnwrapsData.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowInlineWithEnrolledVariants.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowInlineWithEnrolledVariants.1.json new file mode 100644 index 0000000000..de46bebfdf --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowInlineWithEnrolledVariants.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_1" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowPropagatesHTTPErrors.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowPropagatesHTTPErrors.1.json new file mode 100644 index 0000000000..017c030a95 --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowPropagatesHTTPErrors.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows/wf_missing" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCachesForSameUserID.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCachesForSameUserID.1.json new file mode 100644 index 0000000000..a3e7ee8aff --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCachesForSameUserID.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCallsHTTPMethod.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCallsHTTPMethod.1.json new file mode 100644 index 0000000000..a3e7ee8aff --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCallsHTTPMethod.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json new file mode 100644 index 0000000000..a3e7ee8aff --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsCallsHTTPMethodWithRandomDelayWhenBackgrounded.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsNetworkErrorSendsError.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsNetworkErrorSendsError.1.json new file mode 100644 index 0000000000..a3e7ee8aff --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsNetworkErrorSendsError.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsReturnsWorkflows.1.json b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsReturnsWorkflows.1.json new file mode 100644 index 0000000000..a3e7ee8aff --- /dev/null +++ b/Tests/UnitTests/Networking/Backend/__Snapshots__/BackendGetWorkflowsTests/watchOS-testGetWorkflowsReturnsWorkflows.1.json @@ -0,0 +1,30 @@ +{ + "headers" : { + "Authorization" : "Bearer asharedsecret", + "X-Apple-Device-Identifier" : "5D7C0074-07E4-4564-AAA4-4008D0640881", + "X-Client-Build-Version" : "12345", + "X-Client-Bundle-ID" : "com.apple.dt.xctest.tool", + "X-Client-Version" : "17.0.0", + "X-Installation-Method" : "unknown", + "X-Is-Backgrounded" : "false", + "X-Is-Debug-Build" : "true", + "X-Is-Sandbox" : "true", + "X-Observer-Mode-Enabled" : "false", + "X-Platform" : "iOS", + "X-Platform-Device" : "arm64", + "X-Platform-Flavor" : "native", + "X-Platform-Version" : "Version 17.0.0 (Build 21A342)", + "X-Preferred-Locales" : "en_EN", + "X-Retry-Count" : "0", + "X-StoreKit-Version" : "1", + "X-StoreKit2-Enabled" : "false", + "X-Storefront" : "USA", + "X-Version" : "4.0.0", + "content-type" : "application/json" + }, + "request" : { + "body" : null, + "method" : "GET", + "url" : "https://api.revenuecat.com/v1/subscribers/user/workflows" + } +} \ No newline at end of file diff --git a/Tests/UnitTests/Networking/Workflows/WorkflowDetailProcessorTests.swift b/Tests/UnitTests/Networking/Workflows/WorkflowDetailProcessorTests.swift new file mode 100644 index 0000000000..ac180b78dd --- /dev/null +++ b/Tests/UnitTests/Networking/Workflows/WorkflowDetailProcessorTests.swift @@ -0,0 +1,144 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowDetailProcessorTests.swift +// +// Created by RevenueCat. + +import Foundation +import Nimble +import XCTest + +@testable import RevenueCat + +class WorkflowDetailProcessorTests: TestCase { + + private var processor: WorkflowDetailProcessor! + private var fetchedUrls: [String] = [] + + override func setUpWithError() throws { + try super.setUpWithError() + + self.fetchedUrls = [] + self.processor = WorkflowDetailProcessor(cdnFetch: { [weak self] url, completion in + self?.fetchedUrls.append(url) + completion(.success((try? JSONSerialization.data(withJSONObject: ["id": "from_cdn"])) ?? Data())) + }) + } + + func testInlineUnwrapsData() throws { + let envelope: [String: Any] = [ + "action": "inline", + "data": ["id": "wf_inline"] + ] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + self.processor.process(data, completion: completed) + } + + expect(result).to(beSuccess { value in + let parsed = try? JSONSerialization.jsonObject(with: value.workflowData) as? [String: Any] + expect(parsed?["id"] as? String) == "wf_inline" + expect(value.enrolledVariants).to(beNil()) + }) + } + + func testInlineExtractsEnrolledVariants() throws { + let envelope: [String: Any] = [ + "action": "inline", + "data": ["id": "wf1"], + "enrolled_variants": ["a": "b"] + ] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + self.processor.process(data, completion: completed) + } + + expect(result).to(beSuccess { value in + expect(value.enrolledVariants) == ["a": "b"] + }) + } + + func testUseCdnFetchesFromUrl() throws { + let envelope: [String: Any] = [ + "action": "use_cdn", + "url": "https://cdn.example/w.json", + "enrolled_variants": ["x": "y"] + ] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + self.processor.process(data, completion: completed) + } + + expect(self.fetchedUrls) == ["https://cdn.example/w.json"] + expect(result).to(beSuccess { value in + let parsed = try? JSONSerialization.jsonObject(with: value.workflowData) as? [String: Any] + expect(parsed?["id"] as? String) == "from_cdn" + expect(value.enrolledVariants) == ["x": "y"] + }) + } + + func testUnknownActionThrows() throws { + let envelope: [String: Any] = ["action": "other"] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + self.processor.process(data, completion: completed) + } + + expect(result).to(beFailure()) + } + + func testUseCdnPropagatesIOErrorAsCdnFetchFailed() throws { + let failingProcessor = WorkflowDetailProcessor(cdnFetch: { _, completion in + completion(.failure(URLError(.notConnectedToInternet))) + }) + + let envelope: [String: Any] = ["action": "use_cdn", "url": "https://x"] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + failingProcessor.process(data, completion: completed) + } + + expect(result).to(beFailure { error in + guard case WorkflowDetailProcessingError.cdnFetchFailed(let underlying) = error else { + fail("Expected WorkflowDetailProcessingError.cdnFetchFailed, got \(error)") + return + } + expect((underlying as? URLError)?.code) == .notConnectedToInternet + }) + } + + func testMissingDataInInlineThrows() throws { + let envelope: [String: Any] = ["action": "inline"] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + self.processor.process(data, completion: completed) + } + + expect(result).to(beFailure()) + } + + func testMissingUrlInUseCdnThrows() throws { + let envelope: [String: Any] = ["action": "use_cdn"] + let data = try JSONSerialization.data(withJSONObject: envelope) + + let result = waitUntilValue { completed in + self.processor.process(data, completion: completed) + } + + expect(result).to(beFailure()) + } + +} diff --git a/Tests/UnitTests/Networking/Workflows/WorkflowResponseTests.swift b/Tests/UnitTests/Networking/Workflows/WorkflowResponseTests.swift new file mode 100644 index 0000000000..b3ff765149 --- /dev/null +++ b/Tests/UnitTests/Networking/Workflows/WorkflowResponseTests.swift @@ -0,0 +1,219 @@ +// +// Copyright RevenueCat Inc. All Rights Reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// WorkflowResponseTests.swift +// +// Created by RevenueCat. + +import Foundation +import Nimble +import XCTest + +@testable import RevenueCat + +class WorkflowResponseTests: TestCase { + + func testDecodeWorkflowsListResponse() throws { + let json = """ + { + "workflows": [ + { "id": "wf_1", "display_name": "Flow A" } + ], + "ui_config": { + "app": { "colors": {}, "fonts": {} }, + "localizations": {}, + "variable_config": { "variable_compatibility_map": {}, "function_compatibility_map": {} } + } + } + """.data(using: .utf8)! + + let response = try JSONDecoder.default.decode( + WorkflowsListResponse.self, from: json + ) + + expect(response.workflows).to(haveCount(1)) + expect(response.workflows.first?.id) == "wf_1" + expect(response.workflows.first?.displayName) == "Flow A" + } + + func testDecodePublishedWorkflowWithStepsAndTriggerActions() throws { + let json = """ + { + "id": "wf_test", + "display_name": "Test", + "initial_step_id": "step_1", + "steps": { + "step_1": { + "id": "step_1", + "type": "screen", + "trigger_actions": { + "btn_1": { "type": "step", "step_id": "step_2" } + } + } + }, + "screens": {}, + "ui_config": { + "app": { "colors": {}, "fonts": {} }, + "localizations": {}, + "variable_config": { "variable_compatibility_map": {}, "function_compatibility_map": {} } + }, + "content_max_width": 100 + } + """.data(using: .utf8)! + + let workflow = try JSONDecoder.default.decode( + PublishedWorkflow.self, from: json + ) + + expect(workflow.id) == "wf_test" + expect(workflow.initialStepId) == "step_1" + expect(workflow.steps["step_1"]?.triggerActions["btn_1"]?.stepId) == "step_2" + expect(workflow.contentMaxWidth) == 100 + expect(workflow.metadata).to(beNil()) + } + + func testDecodePublishedWorkflowWithoutOptionals() throws { + let json = """ + { + "id": "wf_min", + "display_name": "Minimal", + "initial_step_id": "step_1", + "steps": {}, + "screens": {}, + "ui_config": { + "app": { "colors": {}, "fonts": {} }, + "localizations": {}, + "variable_config": { "variable_compatibility_map": {}, "function_compatibility_map": {} } + } + } + """.data(using: .utf8)! + + let workflow = try JSONDecoder.default.decode( + PublishedWorkflow.self, from: json + ) + + expect(workflow.id) == "wf_min" + expect(workflow.contentMaxWidth).to(beNil()) + } + + func testDecodePublishedWorkflowWithMetadata() throws { + let json = """ + { + "id": "wf_meta", + "display_name": "Meta", + "initial_step_id": "step_1", + "steps": {}, + "screens": {}, + "ui_config": { + "app": { "colors": {}, "fonts": {} }, + "localizations": {}, + "variable_config": { "variable_compatibility_map": {}, "function_compatibility_map": {} } + }, + "metadata": { "some_key": "some_value" } + } + """.data(using: .utf8)! + + let workflow = try JSONDecoder.default.decode(PublishedWorkflow.self, from: json) + + expect(workflow.metadata).toNot(beNil()) + } + + func testDecodeWorkflowTriggerAction() throws { + let json = """ + { "type": "step", "step_id": "step_3" } + """.data(using: .utf8)! + + let action = try JSONDecoder.default.decode(WorkflowTriggerAction.self, from: json) + + expect(action.type) == "step" + expect(action.stepId) == "step_3" + } + + func testDecodeWorkflowTrigger() throws { + let json = """ + { + "name": "Button", + "type": "on_press", + "action_id": "btn_wagcLsIVjN", + "component_id": "wagcLsIVjN" + } + """.data(using: .utf8)! + + let trigger = try JSONDecoder.default.decode(WorkflowTrigger.self, from: json) + + expect(trigger.name) == "Button" + expect(trigger.type) == "on_press" + expect(trigger.actionId) == "btn_wagcLsIVjN" + expect(trigger.componentId) == "wagcLsIVjN" + } + + func testDecodeWorkflowStepDefaults() throws { + let json = """ + { "id": "step_1", "type": "screen" } + """.data(using: .utf8)! + + let step = try JSONDecoder.default.decode(WorkflowStep.self, from: json) + + expect(step.id) == "step_1" + expect(step.type) == "screen" + expect(step.screenId).to(beNil()) + expect(step.paramValues).to(beEmpty()) + expect(step.triggers).to(beEmpty()) + expect(step.outputs).to(beEmpty()) + expect(step.triggerActions).to(beEmpty()) + expect(step.metadata).to(beNil()) + } + + func testDecodeWorkflowStepMatchingActualBackendResponse() throws { + let json = """ + { + "id": "bdMPgNB", + "type": "screen", + "param_values": { + "experiment_id": "expeae100d588", + "experiment_variant": "b", + "is_last_variant_step": true + }, + "triggers": [ + { + "name": "Button", + "type": "on_press", + "action_id": "btn_wagcLsIVjN", + "component_id": "wagcLsIVjN" + } + ], + "outputs": {}, + "trigger_actions": { + "btn_wagcLsIVjN": { + "type": "step", + "step_id": "ztBPCwD" + } + }, + "metadata": null, + "screen_id": "pw458e23295b7841f8" + } + """.data(using: .utf8)! + + let step = try JSONDecoder.default.decode(WorkflowStep.self, from: json) + + expect(step.id) == "bdMPgNB" + expect(step.type) == "screen" + expect(step.screenId) == "pw458e23295b7841f8" + expect(step.triggers).to(haveCount(1)) + expect(step.triggers.first?.name) == "Button" + expect(step.triggers.first?.type) == "on_press" + expect(step.triggers.first?.actionId) == "btn_wagcLsIVjN" + expect(step.triggers.first?.componentId) == "wagcLsIVjN" + expect(step.outputs).to(beEmpty()) + expect(step.triggerActions["btn_wagcLsIVjN"]?.type) == "step" + expect(step.triggerActions["btn_wagcLsIVjN"]?.stepId) == "ztBPCwD" + expect(step.metadata).to(beNil()) + } + +}