Skip to content

Commit b5d5e00

Browse files
committed
Merge branch 'develop' into issue/4778-action-on-edit-address-form
# Conflicts: # WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/EditAddressForm.swift # WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/EditAddressFormViewModel.swift
2 parents 8f84812 + 16ca58b commit b5d5e00

File tree

34 files changed

+901
-228
lines changed

34 files changed

+901
-228
lines changed

Fakes/Fakes/Fakes.generated.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,7 @@ extension ShippingLabelPredefinedOption {
11791179
public static func fake() -> ShippingLabelPredefinedOption {
11801180
.init(
11811181
title: .fake(),
1182+
providerID: .fake(),
11821183
predefinedPackages: .fake()
11831184
)
11841185
}

Networking/Networking/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,27 @@ extension ShippingLabelCustomsForm.Item {
10061006
}
10071007
}
10081008

1009+
extension ShippingLabelPackagesResponse {
1010+
public func copy(
1011+
storeOptions: CopiableProp<ShippingLabelStoreOptions> = .copy,
1012+
customPackages: CopiableProp<[ShippingLabelCustomPackage]> = .copy,
1013+
predefinedOptions: CopiableProp<[ShippingLabelPredefinedOption]> = .copy,
1014+
unactivatedPredefinedOptions: CopiableProp<[ShippingLabelPredefinedOption]> = .copy
1015+
) -> ShippingLabelPackagesResponse {
1016+
let storeOptions = storeOptions ?? self.storeOptions
1017+
let customPackages = customPackages ?? self.customPackages
1018+
let predefinedOptions = predefinedOptions ?? self.predefinedOptions
1019+
let unactivatedPredefinedOptions = unactivatedPredefinedOptions ?? self.unactivatedPredefinedOptions
1020+
1021+
return ShippingLabelPackagesResponse(
1022+
storeOptions: storeOptions,
1023+
customPackages: customPackages,
1024+
predefinedOptions: predefinedOptions,
1025+
unactivatedPredefinedOptions: unactivatedPredefinedOptions
1026+
)
1027+
}
1028+
}
1029+
10091030
extension ShippingLabelPaymentMethod {
10101031
public func copy(
10111032
paymentMethodID: CopiableProp<Int64> = .copy,

Networking/Networking/Model/ShippingLabel/Packages/Predefined package/ShippingLabelPredefinedOption.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ public struct ShippingLabelPredefinedOption: Equatable, GeneratedFakeable {
88
/// The title of the predefined option. It works like an ID, and it is unique.
99
public let title: String
1010

11+
/// The ID of the predefined option (shipping provider), e.g. "usps". This is required for activating predefined packages remotely.
12+
public let providerID: String
13+
1114
/// List of predefined packages
1215
public let predefinedPackages: [ShippingLabelPredefinedPackage]
1316

1417

15-
public init(title: String, predefinedPackages: [ShippingLabelPredefinedPackage]) {
18+
public init(title: String, providerID: String, predefinedPackages: [ShippingLabelPredefinedPackage]) {
1619
self.title = title
20+
self.providerID = providerID
1721
self.predefinedPackages = predefinedPackages
1822
}
1923
}
@@ -25,12 +29,14 @@ extension ShippingLabelPredefinedOption: Decodable {
2529

2630
let title = try container.decode(String.self, forKey: .title)
2731
let predefinedPackages = try container.decodeIfPresent([ShippingLabelPredefinedPackage].self, forKey: .predefinedPackages) ?? []
32+
let providerID = try container.decodeIfPresent(String.self, forKey: .providerID) ?? ""
2833

29-
self.init(title: title, predefinedPackages: predefinedPackages)
34+
self.init(title: title, providerID: providerID, predefinedPackages: predefinedPackages)
3035
}
3136

3237
private enum CodingKeys: String, CodingKey {
3338
case title
3439
case predefinedPackages
40+
case providerID
3541
}
3642
}

Networking/Networking/Model/ShippingLabel/Packages/ShippingLabelPackagesResponse.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Codegen
33

44
/// Represents a list of Shipping Label Packages (custom and predefined).
55
///
6-
public struct ShippingLabelPackagesResponse: Equatable, GeneratedFakeable {
6+
public struct ShippingLabelPackagesResponse: Equatable, GeneratedFakeable, GeneratedCopiable {
77

88
/// The options of the store, like currency symbol and origin country.
99
public let storeOptions: ShippingLabelStoreOptions
@@ -67,15 +67,15 @@ extension ShippingLabelPackagesResponse: Decodable {
6767

6868
if !activatedPredefinedPackages.isEmpty {
6969
let titleOption: String = providerValueDict?["title"] as? String ?? ""
70-
let option = ShippingLabelPredefinedOption(title: titleOption, predefinedPackages: activatedPredefinedPackages)
70+
let option = ShippingLabelPredefinedOption(title: titleOption, providerID: key, predefinedPackages: activatedPredefinedPackages)
7171
predefinedOptions.append(option)
7272
}
7373

7474
let unactivatedPredefinedPackages = packages.filter({ !activatedPredefinedPackages.contains($0) })
7575

7676
if !unactivatedPredefinedPackages.isEmpty {
7777
let titleOption: String = providerValueDict?["title"] as? String ?? ""
78-
let option = ShippingLabelPredefinedOption(title: titleOption, predefinedPackages: unactivatedPredefinedPackages)
78+
let option = ShippingLabelPredefinedOption(title: titleOption, providerID: key, predefinedPackages: unactivatedPredefinedPackages)
7979
unactivatedPredefinedOptions.append(option)
8080
}
8181
})

Networking/Networking/Remote/ShippingLabelRemote.swift

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ public protocol ShippingLabelRemoteProtocol {
1717
func packagesDetails(siteID: Int64,
1818
completion: @escaping (Result<ShippingLabelPackagesResponse, Error>) -> Void)
1919
func createPackage(siteID: Int64,
20-
customPackage: ShippingLabelCustomPackage,
20+
customPackage: ShippingLabelCustomPackage?,
21+
predefinedOption: ShippingLabelPredefinedOption?,
2122
completion: @escaping (Result<Bool, Error>) -> Void)
2223
func loadCarriersAndRates(siteID: Int64,
2324
orderID: Int64,
@@ -130,18 +131,33 @@ public final class ShippingLabelRemote: Remote, ShippingLabelRemoteProtocol {
130131
enqueue(request, mapper: mapper, completion: completion)
131132
}
132133

133-
/// Creates a new custom package.
134+
/// Creates a new custom package or activates a service package.
134135
/// - Parameters:
135136
/// - siteID: Remote ID of the site that owns the shipping label.
136137
/// - customPackage: The custom package that should be created.
138+
/// - predefinedOption: The predefined option (shipping provider and service packages) to activate.
137139
/// - completion: Closure to be executed upon completion.
138140
public func createPackage(siteID: Int64,
139-
customPackage: ShippingLabelCustomPackage,
141+
customPackage: ShippingLabelCustomPackage?,
142+
predefinedOption: ShippingLabelPredefinedOption?,
140143
completion: @escaping (Result<Bool, Error>) -> Void) {
141144
do {
142-
let customPackageDictionary = try customPackage.toDictionary()
143-
let parameters = [
144-
ParameterKey.custom: [customPackageDictionary]
145+
var customPackageList: [[String: Any]] = []
146+
var predefinedOptionDictionary: [String: [String]] = [:]
147+
148+
if let customPackage = customPackage {
149+
let customPackageDictionary = try customPackage.toDictionary()
150+
customPackageList = [customPackageDictionary]
151+
} else if let predefinedOption = predefinedOption {
152+
let packageIDs = predefinedOption.predefinedPackages.map({ $0.id })
153+
predefinedOptionDictionary = [predefinedOption.providerID: packageIDs]
154+
} else {
155+
throw ShippingLabelError.missingPackage
156+
}
157+
158+
let parameters: [String: Any] = [
159+
ParameterKey.custom: customPackageList,
160+
ParameterKey.predefined: predefinedOptionDictionary
145161
]
146162
let path = Path.packages
147163
let request = JetpackRequest(wooApiVersion: .wcConnectV1, method: .post, siteID: siteID, path: path, parameters: parameters)
@@ -308,6 +324,7 @@ private extension ShippingLabelRemote {
308324
static let captionCSV = "caption_csv"
309325
static let json = "json"
310326
static let custom = "custom"
327+
static let predefined = "predefined"
311328
static let canCreatePaymentMethod = "can_create_payment_method"
312329
static let canCreateCustomsForm = "can_create_customs_form"
313330
static let canCreatePackage = "can_create_package"
@@ -320,3 +337,10 @@ private extension ShippingLabelRemote {
320337
static let async = "async"
321338
}
322339
}
340+
341+
// MARK: Errors {
342+
extension ShippingLabelRemote {
343+
enum ShippingLabelError: Error {
344+
case missingPackage
345+
}
346+
}

Networking/NetworkingTests/Mapper/ShippingLabelPackagesMapperTests.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,15 @@ private extension ShippingLabelPackagesMapperTests {
7272
isLetter: false,
7373
dimensions: "28.57 x 22.22 x 15.24")]
7474
let predefinedOption1 = ShippingLabelPredefinedOption(title: "USPS Priority Mail Flat Rate Boxes",
75+
providerID: "usps",
7576
predefinedPackages: predefinedPackages1)
7677

7778
let predefinedPackages2 = [ShippingLabelPredefinedPackage(id: "LargePaddedPouch",
7879
title: "Large Padded Pouch",
7980
isLetter: true,
8081
dimensions: "30.22 x 35.56 x 2.54")]
8182
let predefinedOption2 = ShippingLabelPredefinedOption(title: "DHL Express",
83+
providerID: "dhlexpress",
8284
predefinedPackages: predefinedPackages2)
8385

8486
return [predefinedOption1, predefinedOption2]
@@ -106,7 +108,8 @@ private extension ShippingLabelPackagesMapperTests {
106108
isLetter: false,
107109
dimensions: "44.45 x 31.75 x 7.62")]
108110
let predefinedOption = ShippingLabelPredefinedOption(title: "DHL Express",
109-
predefinedPackages: predefinedPackages)
111+
providerID: "dhlexpress",
112+
predefinedPackages: predefinedPackages)
110113

111114
return predefinedOption
112115
}

Networking/NetworkingTests/Remote/ShippingLabelRemoteTests.swift

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,47 @@ final class ShippingLabelRemoteTests: XCTestCase {
189189

190190
// When
191191
let result: Result<Bool, Error> = waitFor { promise in
192-
remote.createPackage(siteID: self.sampleSiteID, customPackage: self.sampleShippingLabelCustomPackage()) { result in
192+
remote.createPackage(siteID: self.sampleSiteID,
193+
customPackage: ShippingLabelCustomPackage.fake(),
194+
predefinedOption: ShippingLabelPredefinedOption.fake()) { result in
195+
promise(result)
196+
}
197+
}
198+
199+
// Then
200+
let successResponse = try XCTUnwrap(result.get())
201+
XCTAssertTrue(successResponse)
202+
}
203+
204+
func test_createPackage_returns_success_response_with_only_custom_package() throws {
205+
// Given
206+
let remote = ShippingLabelRemote(network: network)
207+
network.simulateResponse(requestUrlSuffix: "packages", filename: "generic_success_data")
208+
209+
// When
210+
let result: Result<Bool, Error> = waitFor { promise in
211+
remote.createPackage(siteID: self.sampleSiteID,
212+
customPackage: ShippingLabelCustomPackage.fake(),
213+
predefinedOption: nil) { result in
214+
promise(result)
215+
}
216+
}
217+
218+
// Then
219+
let successResponse = try XCTUnwrap(result.get())
220+
XCTAssertTrue(successResponse)
221+
}
222+
223+
func test_createPackage_returns_success_response_with_only_service_package() throws {
224+
// Given
225+
let remote = ShippingLabelRemote(network: network)
226+
network.simulateResponse(requestUrlSuffix: "packages", filename: "generic_success_data")
227+
228+
// When
229+
let result: Result<Bool, Error> = waitFor { promise in
230+
remote.createPackage(siteID: self.sampleSiteID,
231+
customPackage: nil,
232+
predefinedOption: ShippingLabelPredefinedOption.fake()) { result in
193233
promise(result)
194234
}
195235
}
@@ -206,7 +246,9 @@ final class ShippingLabelRemoteTests: XCTestCase {
206246

207247
// When
208248
let result: Result<Bool, Error> = waitFor { promise in
209-
remote.createPackage(siteID: self.sampleSiteID, customPackage: self.sampleShippingLabelCustomPackage()) { result in
249+
remote.createPackage(siteID: self.sampleSiteID,
250+
customPackage: ShippingLabelCustomPackage.fake(),
251+
predefinedOption: ShippingLabelPredefinedOption.fake()) { result in
210252
promise(result)
211253
}
212254
}
@@ -218,6 +260,24 @@ final class ShippingLabelRemoteTests: XCTestCase {
218260
XCTAssertEqual(result.failure as? DotcomError, expectedError)
219261
}
220262

263+
func test_createPackage_returns_missingPackage_error_with_no_packages() throws {
264+
// Given
265+
let remote = ShippingLabelRemote(network: network)
266+
267+
// When
268+
let result: Result<Bool, Error> = waitFor { promise in
269+
remote.createPackage(siteID: self.sampleSiteID,
270+
customPackage: nil,
271+
predefinedOption: nil) { result in
272+
promise(result)
273+
}
274+
}
275+
276+
// Then
277+
let expectedError = ShippingLabelRemote.ShippingLabelError.missingPackage
278+
XCTAssertEqual(result.failure as? ShippingLabelRemote.ShippingLabelError, expectedError)
279+
}
280+
221281
func test_loadCarriersAndRates_parses_success_response() throws {
222282
// Given
223283
let remote = ShippingLabelRemote(network: network)
@@ -471,15 +531,6 @@ private extension ShippingLabelRemoteTests {
471531
postcode: "94110-4929")
472532
}
473533

474-
func sampleShippingLabelCustomPackage() -> ShippingLabelCustomPackage {
475-
return ShippingLabelCustomPackage(isUserDefined: true,
476-
title: "Test Package",
477-
isLetter: false,
478-
dimensions: "10 x 10 x 10",
479-
boxWeight: 5,
480-
maxWeight: 1)
481-
}
482-
483534
func sampleShippingLabelCarrierRate() -> ShippingLabelCarrierRate {
484535
let rate = ShippingLabelCarrierRate(title: "USPS - Parcel Select Mail",
485536
insurance: "0",

WooCommerce/Classes/Analytics/WooAnalyticsStat.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ public enum WooAnalyticsStat: String {
233233
case shippingLabelAddressSuggestionsEditSelectedAddressButtonTapped = "shipping_label_address_suggestions_edit_selected_address_button_tapped"
234234
case shippingLabelAddressValidationFailed = "shipping_label_address_validation_failed"
235235
case shippingLabelAddressValidationSucceeded = "shipping_label_address_validation_succeeded"
236+
case shippingLabelAddPackageTapped = "shipping_label_add_package_tapped"
237+
case shippingLabelPackageAddedSuccessfully = "shipping_label_package_added_successfully"
238+
case shippingLabelAddPackageFailed = "shipping_label_add_package_failed"
236239

237240
// MARK: Receipt Events
238241
//

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/CountrySelectorCommand.swift

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ final class CountrySelectorCommand: ObservableListSelectorCommand {
99

1010
/// Original array of countries.
1111
///
12-
private var countries: [Country]
12+
private let countries: [Country]
1313

1414
/// Data to display
1515
///
@@ -41,13 +41,6 @@ final class CountrySelectorCommand: ObservableListSelectorCommand {
4141
cell.textLabel?.text = model.name
4242
}
4343

44-
/// Resets countries data.
45-
///
46-
func resetCountries(_ countries: [Country]) {
47-
self.countries = countries
48-
self.data = countries
49-
}
50-
5144
/// Filter available countries that contains a given search term.
5245
///
5346
func filterCountries(term: String) {

0 commit comments

Comments
 (0)