Skip to content

Commit 6b179d6

Browse files
authored
Surfaces request data in Search and Browse Responses (#176)
1 parent 88b872a commit 6b179d6

File tree

10 files changed

+484
-3
lines changed

10 files changed

+484
-3
lines changed

AutocompleteClient.xcodeproj/project.pbxproj

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
8A5572812A1429930041DB65 /* CIOBrowseGroupsQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A5572802A1429930041DB65 /* CIOBrowseGroupsQuery.swift */; };
8080
8A5572832A1433350041DB65 /* CIOBrowseGroupsQueryBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A5572822A1433350041DB65 /* CIOBrowseGroupsQueryBuilder.swift */; };
8181
8A5572852A143E840041DB65 /* ConstructorIOBrowseGroupsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A5572842A143E840041DB65 /* ConstructorIOBrowseGroupsTests.swift */; };
82+
8AE1429F2A53832E003E7E0E /* response_browse_json.json in Resources */ = {isa = PBXBuildFile; fileRef = 8AE1429E2A53832E003E7E0E /* response_browse_json.json */; };
83+
8AE142A12A538384003E7E0E /* BrowseResponseParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE142A02A538384003E7E0E /* BrowseResponseParserTest.swift */; };
8284
8D0308702A1ED67C0084AB85 /* CIOBrowseFacetOptionsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D03086F2A1ED67C0084AB85 /* CIOBrowseFacetOptionsResponse.swift */; };
8385
8D0308722A1ED6FC0084AB85 /* CIOBrowseFacetOptionsQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D0308712A1ED6FC0084AB85 /* CIOBrowseFacetOptionsQuery.swift */; };
8486
8D0308742A1ED8AF0084AB85 /* AbstractBrowseFacetOptionsResponseParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D0308732A1ED8AF0084AB85 /* AbstractBrowseFacetOptionsResponseParser.swift */; };
@@ -432,6 +434,8 @@
432434
8A5572802A1429930041DB65 /* CIOBrowseGroupsQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOBrowseGroupsQuery.swift; sourceTree = "<group>"; };
433435
8A5572822A1433350041DB65 /* CIOBrowseGroupsQueryBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOBrowseGroupsQueryBuilder.swift; sourceTree = "<group>"; };
434436
8A5572842A143E840041DB65 /* ConstructorIOBrowseGroupsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstructorIOBrowseGroupsTests.swift; sourceTree = "<group>"; };
437+
8AE1429E2A53832E003E7E0E /* response_browse_json.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = response_browse_json.json; sourceTree = "<group>"; };
438+
8AE142A02A538384003E7E0E /* BrowseResponseParserTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrowseResponseParserTest.swift; sourceTree = "<group>"; };
435439
8D03086F2A1ED67C0084AB85 /* CIOBrowseFacetOptionsResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOBrowseFacetOptionsResponse.swift; sourceTree = "<group>"; };
436440
8D0308712A1ED6FC0084AB85 /* CIOBrowseFacetOptionsQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOBrowseFacetOptionsQuery.swift; sourceTree = "<group>"; };
437441
8D0308732A1ED8AF0084AB85 /* AbstractBrowseFacetOptionsResponseParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbstractBrowseFacetOptionsResponseParser.swift; sourceTree = "<group>"; };
@@ -751,6 +755,7 @@
751755
children = (
752756
F6D86B15216BAD7F00077388 /* SearchResponseParserTests.swift */,
753757
F64F46A51F595B980094C697 /* CIOAutocompleteResponseParserTests.swift */,
758+
8AE142A02A538384003E7E0E /* BrowseResponseParserTest.swift */,
754759
BFC9502F25D499B600118D4C /* RecommendationsResponseParserTests.swift */,
755760
F674157A204D489B004F313B /* MockResponseParserDelegate.swift */,
756761
);
@@ -854,7 +859,6 @@
854859
08C1E6042193BE3600A2E24E /* CIOTrackPurchaseData.swift */,
855860
088F7D1D210FA3C6005B9FB4 /* CIOTrackInputFocusData.swift */,
856861
BFC9503825D742.6.2118D4C /* CIOTrackRecommendationResultClickData.swift */,
857-
8D4F1ACD29357FA000803327 /* CIOBrowseItemsQuery.swift */,
858862
BFC9503A25D74D3F00118D4C /* CIOTrackRecommendationResultsViewData.swift */,
859863
F6DF7B9320849E8D00A7CDAD /* CIOTrackSearchResultClickData.swift */,
860864
F6D2E9CB20E21022007F8761 /* CIOTrackSearchResultsLoadedData.swift */,
@@ -1520,6 +1524,7 @@
15201524
isa = PBXGroup;
15211525
children = (
15221526
8D5336CB2A1ECCCE00AA4D9B /* response_browse_facet_options_json.json */,
1527+
8AE1429E2A53832E003E7E0E /* response_browse_json.json */,
15231528
8D5336C82A1ECC7400AA4D9B /* response_browse_facets_json.json */,
15241529
F6B4627E1F6BA61C0082C20B /* response_json_multiple_groups.json */,
15251530
F64F46B01F5970140094C697 /* response_json_single_section.json */,
@@ -2224,6 +2229,7 @@
22242229
F6F1D707234B693D0092341D /* response_search_json_variations.json in Resources */,
22252230
F6F1D70B234B6FD50092341D /* response_search_json_variation_custom_data.json in Resources */,
22262231
F6B4627F1F6BA61C0082C20B /* response_json_multiple_groups.json in Resources */,
2232+
8AE1429F2A53832E003E7E0E /* response_browse_json.json in Resources */,
22272233
7D54FF8428E3BFA400A584E3 /* response_quiz_next_question.json in Resources */,
22282234
F67868DF22295CA200C76C0D /* response_search_redirect.json in Resources */,
22292235
F65BBCAE214FC99E007FEB22 /* response_search_json.json in Resources */,
@@ -2616,6 +2622,7 @@
26162622
F66B216921DF8A8C00AAB030 /* SearchBarTextFieldTests.swift in Sources */,
26172623
089399E32161C67D00BFE3D9 /* TrackSearchResultsLoadedRequestBuilder.swift in Sources */,
26182624
F64F46AD1F5963AF0094C697 /* Bundle+Test.swift in Sources */,
2625+
8AE142A12A538384003E7E0E /* BrowseResponseParserTest.swift in Sources */,
26192626
7DDA7D9728DCFDC4004C8AC8 /* QuizzesQueryRequestBuilderTests.swift in Sources */,
26202627
F174C1ED1F5F5AC1009E354B /* NSString+RangeOfCharactersTest.swift in Sources */,
26212628
F66B217321E26E0A00AAB030 /* DefaultSearchItemCellTests.swift in Sources */,

AutocompleteClient/FW/API/Parser/Browse/BrowseResponseParser.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class BrowseResponseParser: AbstractBrowseResponseParser {
3131
let collection: CIOCollectionData? = CIOCollectionData(json: response["collection"] as? JSONObject)
3232
let resultID = json?["result_id"] as? String ?? ""
3333
let resultSources: CIOResultSources? = CIOResultSources(json: response["result_sources"] as? JSONObject)
34+
35+
guard let request: JSONObject = json?["request"] as? JSONObject else {
36+
throw CIOError(errorType: .invalidResponse)
37+
}
3438

3539
return CIOBrowseResponse(
3640
facets: facets,
@@ -40,7 +44,8 @@ class BrowseResponseParser: AbstractBrowseResponseParser {
4044
totalNumResults: totalNumResults,
4145
resultID: resultID,
4246
collection: collection,
43-
resultSources: resultSources
47+
resultSources: resultSources,
48+
request: request
4449
)
4550
} catch {
4651
throw CIOError(errorType: .invalidResponse)

AutocompleteClient/FW/API/Parser/Search/SearchResponseParser.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ class SearchResponseParser: AbstractSearchResponseParser {
3232
let resultID = json?["result_id"] as? String ?? ""
3333
let resultSources: CIOResultSources? = CIOResultSources(json: response["result_sources"] as? JSONObject)
3434
let refinedContent: [CIORefinedContent] = refinedContentObj?.compactMap({ obj in return CIORefinedContent(json: obj) }) ?? []
35+
36+
guard let request: JSONObject = json?["request"] as? JSONObject else {
37+
throw CIOError(errorType: .invalidResponse)
38+
}
3539

3640
return CIOSearchResponse(
3741
facets: facets,
@@ -42,7 +46,8 @@ class SearchResponseParser: AbstractSearchResponseParser {
4246
totalNumResults: totalNumResults,
4347
resultID: resultID,
4448
resultSources: resultSources,
45-
refinedContent: refinedContent
49+
refinedContent: refinedContent,
50+
request: request
4651
)
4752
} catch {
4853
throw CIOError(errorType: .invalidResponse)

AutocompleteClient/FW/Logic/Result/Responses/CIOBrowseResponse.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,9 @@ public struct CIOBrowseResponse {
5151
Sources of the result set
5252
*/
5353
public let resultSources: CIOResultSources?
54+
55+
/**
56+
Request object used to retrieve the Browse Response
57+
*/
58+
public var request: JSONObject
5459
}

AutocompleteClient/FW/Logic/Result/Responses/CIOSearchResponse.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,9 @@ public struct CIOSearchResponse {
6363
public var isRedirect: Bool {
6464
return self.redirectInfo != nil
6565
}
66+
67+
/**
68+
Request object used to retrieve the Search Response
69+
*/
70+
public var request: JSONObject
6671
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//
2+
// BrowseResponseParserTests.swift
3+
// AutocompleteClientTests
4+
//
5+
// Copyright © Constructor.io. All rights reserved.
6+
// http://constructor.io/
7+
//
8+
9+
@testable import ConstructorAutocomplete
10+
import XCTest
11+
12+
class BrowseResponseParserTests: XCTestCase {
13+
14+
var parser: BrowseResponseParser!
15+
16+
override func setUp() {
17+
super.setUp()
18+
// Put setup code here. This method is called before the invocation of each test method in the class.
19+
self.parser = BrowseResponseParser()
20+
}
21+
22+
override func tearDown() {
23+
// Put teardown code here. This method is called after the invocation of each test method in the class.
24+
super.tearDown()
25+
}
26+
27+
func testBrowseParser_parsingRequestObjectAsJson_hasRelevantFields() {
28+
let data = TestResource.load(name: TestResource.Response.browseJSONFilename)
29+
do {
30+
let response = try self.parser.parse(browseResponseData: data)
31+
let requestJson = response.request
32+
33+
let fmtOptions = requestJson["fmt_options"] as? JSONObject
34+
let groupsMaxDepth = fmtOptions?["groups_max_depth"]
35+
let groupsStart = fmtOptions?["groups_start"]
36+
37+
XCTAssertNotNil(fmtOptions, "Valid fmtOptions should be correctly parsed")
38+
XCTAssertEqual(groupsMaxDepth as? Int, Optional(1), "Valid groupsMaxDepth should be correctly parsed")
39+
XCTAssertEqual(groupsStart as? String, "current", "Valid groupsStart should be correctly parsed")
40+
XCTAssertEqual(requestJson["num_results_per_page"] as? Int, Optional(20), "Valid numResults should be correctly parsed")
41+
XCTAssertEqual(requestJson["page"] as? Int, Optional(1), "Valid page should be correctly parsed")
42+
XCTAssertEqual(requestJson["section"] as? String, "Products", "Valid section should be correctly parsed")
43+
XCTAssertEqual(requestJson["sort_by"] as? String, "relevance", "Valid sortBy should be correctly parsed")
44+
XCTAssertEqual(requestJson["sort_order"] as? String, "descending", "Valid sortOrder should be correctly parsed")
45+
XCTAssertEqual(requestJson["term"] as? String, "", "Valid term should be correctly parsed")
46+
XCTAssertEqual(requestJson["browse_filter_name"] as? String, "group_id", "Valid filterName should be correctly parsed")
47+
XCTAssertEqual(requestJson["browse_filter_value"] as? String, "BrandA", "Valid filterValue should be correctly parsed")
48+
XCTAssertNotNil(requestJson["features"], "Valid features should be correctly parsed")
49+
XCTAssertNotNil(requestJson["feature_variants"], "Valid featureVariants should be correctly parsed")
50+
XCTAssertNotNil(requestJson["searchandized_items"], "Valid searchandizedItems should be correctly parsed")
51+
52+
} catch {
53+
XCTFail("Parse should never throw an exception when a valid JSON string is passed.")
54+
}
55+
}
56+
}

AutocompleteClientTests/FW/API/Parser/SearchResponseParserTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,30 @@ class SearchResponseParserTests: XCTestCase {
172172
XCTFail("Parse should never throw an exception when a valid JSON string is passed.")
173173
}
174174
}
175+
176+
func testSearchParser_parsingRequestObjectAsJson_hasRelevantFields() {
177+
let data = TestResource.load(name: TestResource.Response.searchJSONFilename)
178+
do {
179+
let response = try self.parser.parse(searchResponseData: data)
180+
let requestJson = response.request
181+
182+
let fmtOptions = requestJson["fmt_options"] as? JSONObject
183+
let groupsMaxDepth = fmtOptions?["groups_max_depth"]
184+
let groupsStart = fmtOptions?["groups_start"]
185+
186+
XCTAssertNotNil(fmtOptions, "Valid fmtOptions should be correctly parsed")
187+
XCTAssertEqual(groupsMaxDepth as? Int, Optional(1), "Valid groupsMaxDepth should be correctly parsed")
188+
XCTAssertEqual(groupsStart as? String, "current", "Valid groupsStart should be correctly parsed")
189+
XCTAssertEqual(requestJson["num_results_per_page"] as? Int, Optional(24), "Valid numResults should be correctly parsed")
190+
XCTAssertEqual(requestJson["page"] as? Int, Optional(1), "Valid page should be correctly parsed")
191+
XCTAssertEqual(requestJson["section"] as? String, "Products", "Valid section should be correctly parsed")
192+
XCTAssertEqual(requestJson["sort_by"] as? String, "relevance", "Valid sortBy should be correctly parsed")
193+
XCTAssertEqual(requestJson["sort_order"] as? String, "descending", "Valid sortOrder should be correctly parsed")
194+
XCTAssertEqual(requestJson["term"] as? String, "banana", "Valid term should be correctly parsed")
195+
XCTAssertEqual(requestJson["us"] as? [String], ["COUNTRY_US"], "Valid userSegment should be correctly parsed")
196+
197+
} catch {
198+
XCTFail("Parse should never throw an exception when a valid JSON string is passed.")
199+
}
200+
}
175201
}

AutocompleteClientTests/FW/Logic/Worker/ConstructorIOIntegrationTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,9 @@ class ConstructorIOIntegrationTests: XCTestCase {
432432
let responseData = response.data!
433433
let results = responseData.results
434434
XCTAssertFalse(results.isEmpty)
435+
436+
let request = responseData.request
437+
XCTAssertNotNil(request)
435438

436439
expectation.fulfill()
437440
})
@@ -705,6 +708,9 @@ class ConstructorIOIntegrationTests: XCTestCase {
705708
let responseData = response.data!
706709
let results = responseData.results
707710
XCTAssertFalse(results.isEmpty)
711+
712+
let request = responseData.request
713+
XCTAssertNotNil(request)
708714

709715
expectation.fulfill()
710716
})

AutocompleteClientTests/Resources/TestResource.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct TestResource {
1616
static let numberOfSectionsInMultipleSectionsResponse = 2
1717

1818
static let searchJSONFilename = "response_search_json"
19+
static let browseJSONFilename = "response_browse_json"
1920
static let browseFacetsJSONFilename = "response_browse_facets_json"
2021
static let browseFacetOptionsJSONFilename = "response_browse_facet_options_json"
2122
static let searchJSONRedirectFile = "response_search_redirect"

0 commit comments

Comments
 (0)