Skip to content

Commit c8cf0c6

Browse files
authored
Merge pull request #478 from Iterable/MOB-2921-trackpurchase-api
[MOB-2921] update commerceitem to allow optional fields
2 parents a6eee55 + dce428e commit c8cf0c6

File tree

4 files changed

+120
-34
lines changed

4 files changed

+120
-34
lines changed

swift-sdk/CommerceItem.swift

+80-28
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,101 @@
44

55
import UIKit
66

7-
/**
8-
`CommerceItem` represents a product. These are used by the commerce API; see [IterableAPI trackPurchase:items:dataFields:]
9-
*/
7+
/// `CommerceItem` represents a product
8+
/// - SeeAlso: IterableAPI.track(purchase withTotal: items:)
109
@objcMembers public class CommerceItem: NSObject {
11-
/** id of this product */
10+
/// id of this product
1211
public var id: String
1312

14-
/** name of this product */
13+
/// name of this product
1514
public var name: String
1615

17-
/** price of this product */
16+
/// price of this product
1817
public var price: NSNumber
1918

20-
/** quantity of this product */
19+
/// quantity of this product
2120
public var quantity: UInt
2221

23-
/**
24-
Creates a `CommerceItem` with the specified properties
25-
26-
- parameters:
27-
- id: id of the product
28-
- name: name of the product
29-
- price: price of the product
30-
- quantity: quantity of the product
31-
32-
- returns: an instance of `CommerceItem` with the specified properties
33-
*/
34-
public init(id: String, name: String, price: NSNumber, quantity: UInt) {
22+
/// SKU of this product
23+
public var sku: String?
24+
25+
/// description of the product
26+
/// the class field is named `itemDescription` to avoid iOS namespace (`description`)
27+
public var itemDescription: String?
28+
29+
/// URL of the product
30+
public var url: String?
31+
32+
/// URL of the product's image
33+
public var imageUrl: String?
34+
35+
/// categories this product belongs to
36+
/// each category is a breadcrumb in list form
37+
public var categories: [String]?
38+
39+
/// Creates a `CommerceItem` with the specified properties
40+
///
41+
/// - Parameters:
42+
/// - id: id of the product
43+
/// - name: name of the product
44+
/// - price: price of the product
45+
/// - quantity: quantity of the product
46+
/// - sku: SKU of the eproduct
47+
/// - description: description of the product
48+
/// - url: URL of the product
49+
/// - imageUrl: URL of the product's image
50+
/// - categories: categories this product belongs to
51+
///
52+
/// - returns: an instance of `CommerceItem` with the specified properties
53+
public init(id: String,
54+
name: String,
55+
price: NSNumber,
56+
quantity: UInt,
57+
sku: String? = nil,
58+
description: String? = nil,
59+
url: String? = nil,
60+
imageUrl: String? = nil,
61+
categories: [String]? = nil) {
3562
self.id = id
3663
self.name = name
3764
self.price = price
3865
self.quantity = quantity
66+
self.sku = sku
67+
self.itemDescription = description
68+
self.url = url
69+
self.imageUrl = imageUrl
70+
self.categories = categories
3971
}
4072

41-
/**
42-
A Dictionary respresentation of this item
43-
44-
- returns: An NSDictionary representing this item
45-
*/
73+
/// A `Dictionary` representation of this item
74+
///
75+
/// - returns: An `Dictionary` representing this item
4676
public func toDictionary() -> [AnyHashable: Any] {
47-
["id": id,
48-
"name": name,
49-
"price": price,
50-
"quantity": quantity]
77+
var dictionary: [AnyHashable: Any] = [JsonKey.CommerceItem.id: id,
78+
JsonKey.CommerceItem.name: name,
79+
JsonKey.CommerceItem.price: price,
80+
JsonKey.CommerceItem.quantity: quantity]
81+
82+
if let sku = sku {
83+
dictionary[JsonKey.CommerceItem.sku] = sku
84+
}
85+
86+
if let description = itemDescription {
87+
dictionary[JsonKey.CommerceItem.description] = description
88+
}
89+
90+
if let url = url {
91+
dictionary[JsonKey.CommerceItem.url] = url
92+
}
93+
94+
if let imageUrl = imageUrl {
95+
dictionary[JsonKey.CommerceItem.imageUrl] = imageUrl
96+
}
97+
98+
if let categories = categories {
99+
dictionary[JsonKey.CommerceItem.categories] = categories
100+
}
101+
102+
return dictionary
51103
}
52104
}

swift-sdk/Constants.swift

+12
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ enum JsonKey {
159159
static let user = "user"
160160
}
161161

162+
enum CommerceItem {
163+
static let id = "id"
164+
static let name = "name"
165+
static let price = "price"
166+
static let quantity = "quantity"
167+
static let sku = "sku"
168+
static let description = "description"
169+
static let imageUrl = "imageUrl"
170+
static let url = "url"
171+
static let categories = "categories"
172+
}
173+
162174
enum Device {
163175
static let localizedModel = "localizedModel"
164176
static let vendorId = "identifierForVendor"

swift-sdk/Internal/RequestCreator.swift

+1-5
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,8 @@ struct RequestCreator {
8989
ITBError("Both email and userId are nil")
9090
return .failure(IterableError.general(description: "Both email and userId are nil"))
9191
}
92-
93-
var itemsToSerialize = [[AnyHashable: Any]]()
9492

95-
for item in items {
96-
itemsToSerialize.append(item.toDictionary())
97-
}
93+
let itemsToSerialize = items.map { $0.toDictionary() }
9894

9995
var apiUserDict = [AnyHashable: Any]()
10096

tests/unit-tests/CommerceItemTests.swift

+27-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import XCTest
77
@testable import IterableSDK
88

99
class CommerceItemTests: XCTestCase {
10-
func testToDictionary() {
10+
func testToDictionaryWithRequiredFields() {
1111
let commerceItemDictionary = CommerceItem(id: "commerceItemId", name: "commerceItemName", price: 6, quantity: 9000).toDictionary()
1212

1313
let expected: [AnyHashable: Any] = ["id": "commerceItemId",
@@ -17,4 +17,30 @@ class CommerceItemTests: XCTestCase {
1717

1818
XCTAssertEqual(NSDictionary(dictionary: commerceItemDictionary), NSDictionary(dictionary: expected))
1919
}
20+
21+
func testToDictionaryWithAllFields() {
22+
let itemDictionary = CommerceItem(id: "THINKTANK",
23+
name: "Tachikoma",
24+
price: 7.62,
25+
quantity: 9,
26+
sku: "kusanagi",
27+
description: "spider type multi leg/multi ped combat vehicle equipped with AI",
28+
url: "stand-alone-complex",
29+
imageUrl: "laughing-man",
30+
categories: ["section 9",
31+
"personnel transport"]).toDictionary()
32+
33+
let expected: [AnyHashable: Any] = ["id": "THINKTANK",
34+
"name": "Tachikoma",
35+
"price": 7.62,
36+
"quantity": 9,
37+
"sku": "kusanagi",
38+
"description": "spider type multi leg/multi ped combat vehicle equipped with AI",
39+
"url": "stand-alone-complex",
40+
"imageUrl": "laughing-man",
41+
"categories": ["section 9",
42+
"personnel transport"]]
43+
44+
XCTAssertEqual(NSDictionary(dictionary: itemDictionary), NSDictionary(dictionary: expected))
45+
}
2046
}

0 commit comments

Comments
 (0)