11import OHHTTPStubs
22@testable @_spi ( STP) import StripeCore
33@testable @_spi ( STP) import StripePaymentSheet
4+ @testable @_spi ( STP) import StripeUICore
45import XCTest
56
67@MainActor
@@ -54,7 +55,7 @@ final class CheckoutDefaultsInitializationTests: XCTestCase {
5455 line1: " 123 Shipping St " ,
5556 city: " San Francisco " ,
5657 state: " CA " ,
57- postalCode: " 94105 "
58+ postalCode: " 94105-1234 "
5859 )
5960 configuration. defaults. shippingDetails = shippingDetails
6061
@@ -68,25 +69,171 @@ final class CheckoutDefaultsInitializationTests: XCTestCase {
6869 XCTAssertEqual ( requests [ 1 ] . params [ " tax_region[country] " ] , " US " )
6970 XCTAssertEqual ( requests [ 1 ] . params [ " tax_region[line1] " ] , " 123 Shipping St " )
7071 XCTAssertEqual ( requests [ 1 ] . params [ " tax_region[city] " ] , " San Francisco " )
72+ XCTAssertEqual ( requests [ 1 ] . params [ " tax_region[postal_code] " ] , " 94105 " )
7173 XCTAssertEqual ( checkout. session. shippingAddress? . name, " Shipping Name " )
74+ XCTAssertEqual ( checkout. session. shippingAddress? . address. postalCode, " 94105 " )
75+ XCTAssertEqual (
76+ checkout. getPaymentElement ( ) . paymentSheetFlowController. configuration. shippingDetails ( ) ? . address. postalCode,
77+ " 94105 "
78+ )
79+ XCTAssertEqual (
80+ checkout. getPaymentElement ( ) . embeddedPaymentElement. configuration. shippingDetails ( ) ? . address. postalCode,
81+ " 94105 "
82+ )
83+ }
84+
85+ func testInitDoesNotApplyShippingDefaultWhenShippingAddressElementReturnsNil( ) async throws {
86+ // Given a Checkout Session that uses shipping for tax
87+ stubCheckoutSessionRequests ( automaticTaxAddressSource: " shipping " )
88+
89+ var configuration = Checkout . Configuration ( clientSecret: clientSecret, returnURL: " stripe-ios-test://checkout-return " )
90+ configuration. apiClient = STPAPIClient ( publishableKey: " pk_test_123 " )
91+ var shippingDetails = Checkout . Configuration. Defaults. ShippingDetails ( )
92+ shippingDetails. name = " Shipping Name "
93+ shippingDetails. address = . init(
94+ country: " US " ,
95+ line1: " 123 Shipping St " ,
96+ city: " San Francisco " ,
97+ state: " CA " ,
98+ postalCode: " 12 "
99+ )
100+ configuration. defaults. shippingDetails = shippingDetails
101+
102+ // When Checkout initializes
103+ let checkout = try await Checkout ( configuration: configuration)
104+
105+ // Then the invalid shipping default remains in the SAE for correction but is not applied
106+ XCTAssertNotNil ( checkout. getPaymentElement ( ) )
107+ XCTAssertEqual ( requestRecorder. requests. map ( \. kind) , [ . initSession] )
108+ XCTAssertNil ( checkout. session. shippingAddress)
109+ XCTAssertEqual (
110+ checkout. getShippingAddressElement ( ) . addressViewController. configuration. defaultValues. address. postalCode,
111+ " 12 "
112+ )
113+ let normalizedShippingAddress = await checkout. getShippingAddressElement ( ) . normalizedInitialShippingAddress ( )
114+ XCTAssertNil ( normalizedShippingAddress)
115+ }
116+
117+ func testInitDropsStateWhenShippingAddressElementDoesNotCollectState( ) async throws {
118+ // Given an address with a state for a country whose form does not collect one
119+ stubCheckoutSessionRequests ( automaticTaxAddressSource: " shipping " , allowedShippingCountries: [ " AT " ] )
120+
121+ var configuration = Checkout . Configuration ( clientSecret: clientSecret, returnURL: " stripe-ios-test://checkout-return " )
122+ configuration. apiClient = STPAPIClient ( publishableKey: " pk_test_123 " )
123+ var shippingDetails = Checkout . Configuration. Defaults. ShippingDetails ( )
124+ shippingDetails. name = " Shipping Name "
125+ shippingDetails. address = . init(
126+ country: " AT " ,
127+ line1: " Karntner Strasse 1 " ,
128+ city: " Vienna " ,
129+ state: " Vienna " ,
130+ postalCode: " 1010 "
131+ )
132+ configuration. defaults. shippingDetails = shippingDetails
133+
134+ // When Checkout initializes
135+ let checkout = try await Checkout ( configuration: configuration)
136+ let requests = requestRecorder. requests
137+
138+ // Then the SAE does not show or return the provided state
139+ XCTAssertNil ( checkout. getShippingAddressElement ( ) . addressViewController. addressSection? . state)
140+ XCTAssertEqual ( requests. map ( \. kind) , [ . initSession, . updateSession] )
141+ XCTAssertNil ( requests [ 1 ] . params [ " tax_region[state] " ] )
142+ XCTAssertNil ( checkout. session. shippingAddress? . address. state)
143+ }
144+
145+ func testInitLeavesStateBlankWhenShippingAddressElementDoesNotRecognizeState( ) async throws {
146+ // Given a Brazilian state name that does not match an SDK state name or code
147+ stubCheckoutSessionRequests ( automaticTaxAddressSource: " shipping " , allowedShippingCountries: [ " BR " ] )
148+
149+ var configuration = Checkout . Configuration ( clientSecret: clientSecret, returnURL: " stripe-ios-test://checkout-return " )
150+ configuration. apiClient = STPAPIClient ( publishableKey: " pk_test_123 " )
151+ var shippingDetails = Checkout . Configuration. Defaults. ShippingDetails ( )
152+ shippingDetails. name = " Shipping Name "
153+ shippingDetails. address = . init(
154+ country: " BR " ,
155+ line1: " Avenida Sete de Setembro 1 " ,
156+ city: " Porto Velho " ,
157+ state: " Rondonia " ,
158+ postalCode: " 76801-020 "
159+ )
160+ configuration. defaults. shippingDetails = shippingDetails
161+
162+ // When Checkout initializes
163+ let checkout = try await Checkout ( configuration: configuration)
164+
165+ // Then the required state dropdown remains blank and the invalid address is not applied
166+ XCTAssertEqual ( checkout. getShippingAddressElement ( ) . addressViewController. addressSection? . state? . rawData, " " )
167+ XCTAssertEqual ( requestRecorder. requests. map ( \. kind) , [ . initSession] )
168+ XCTAssertNil ( checkout. session. shippingAddress)
169+ }
170+
171+ func testInitDoesNotApplyDisallowedShippingDefault( ) async throws {
172+ // Given a Checkout Session that only allows US shipping addresses
173+ stubCheckoutSessionRequests ( automaticTaxAddressSource: " shipping " , allowedShippingCountries: [ " US " ] )
174+
175+ var configuration = Checkout . Configuration ( clientSecret: clientSecret, returnURL: " stripe-ios-test://checkout-return " )
176+ configuration. apiClient = STPAPIClient ( publishableKey: " pk_test_123 " )
177+ var shippingDetails = Checkout . Configuration. Defaults. ShippingDetails ( )
178+ shippingDetails. name = " Shipping Name "
179+ shippingDetails. address = . init(
180+ country: " CA " ,
181+ line1: " 123 Front St " ,
182+ city: " Toronto " ,
183+ state: " ON " ,
184+ postalCode: " M5J 2N1 "
185+ )
186+ configuration. defaults. shippingDetails = shippingDetails
187+
188+ // When Checkout initializes
189+ let checkout = try await Checkout ( configuration: configuration)
190+
191+ // Then the SAE rejects the default and Checkout does not apply it
192+ XCTAssertNotNil ( checkout. getPaymentElement ( ) )
193+ XCTAssertEqual ( requestRecorder. requests. map ( \. kind) , [ . initSession] )
194+ XCTAssertNil ( checkout. session. shippingAddress)
195+ XCTAssertTrue (
196+ checkout. getShippingAddressElement ( ) . addressViewController. configuration. defaultValues. address. isEmpty
197+ )
198+ }
199+
200+ func testInitWithoutShippingDefaultDoesNotPerformShippingUpdate( ) async throws {
201+ // Given a Checkout Session that uses shipping for tax
202+ stubCheckoutSessionRequests ( automaticTaxAddressSource: " shipping " )
203+
204+ var configuration = Checkout . Configuration ( clientSecret: clientSecret, returnURL: " stripe-ios-test://checkout-return " )
205+ configuration. apiClient = STPAPIClient ( publishableKey: " pk_test_123 " )
206+
207+ // When Checkout initializes
208+ let checkout = try await Checkout ( configuration: configuration)
209+
210+ // Then Checkout does not manufacture or apply a shipping default
211+ XCTAssertNotNil ( checkout. getPaymentElement ( ) )
212+ XCTAssertEqual ( requestRecorder. requests. map ( \. kind) , [ . initSession] )
213+ XCTAssertNil ( checkout. session. shippingAddress)
72214 }
73215
74216 // MARK: - Stubs
75217
76218 private func stubCheckoutSessionRequests(
77- automaticTaxAddressSource: String = " billing "
219+ automaticTaxAddressSource: String = " billing " ,
220+ allowedShippingCountries: [ String ] = [ " US " , " CA " ]
78221 ) {
79222 CheckoutTestHelpers . stubCheckoutSessionRequests (
80223 sessionId: sessionId,
81224 requestRecorder: requestRecorder,
82225 sessionJSON: { [ self ] in
83- sessionJSON ( automaticTaxAddressSource: automaticTaxAddressSource)
226+ sessionJSON (
227+ automaticTaxAddressSource: automaticTaxAddressSource,
228+ allowedShippingCountries: allowedShippingCountries
229+ )
84230 }
85231 )
86232 }
87233
88234 private func sessionJSON(
89- automaticTaxAddressSource: String = " billing "
235+ automaticTaxAddressSource: String = " billing " ,
236+ allowedShippingCountries: [ String ] = [ " US " , " CA " ]
90237 ) -> [ AnyHashable : Any ] {
91238 var json = CheckoutTestHelpers . openSessionJSON
92239 json [ " session_id " ] = sessionId
@@ -95,7 +242,7 @@ final class CheckoutDefaultsInitializationTests: XCTestCase {
95242 " automatic_tax_enabled " : true ,
96243 " automatic_tax_address_source " : " session. \( automaticTaxAddressSource) " ,
97244 ]
98- json [ " shipping_address_collection " ] = [ " allowed_countries " : [ " US " , " CA " ] ]
245+ json [ " shipping_address_collection " ] = [ " allowed_countries " : allowedShippingCountries ]
99246 return json
100247 }
101248}
0 commit comments