Skip to content

Commit 23caaca

Browse files
authored
feat: Expose send() method public in BoxClient (#843)
1 parent a7c69a7 commit 23caaca

File tree

9 files changed

+697
-121
lines changed

9 files changed

+697
-121
lines changed

BoxSDK.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
0501990C282423970085003B /* BoxClientIntegrationSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0501990B282423970085003B /* BoxClientIntegrationSpecs.swift */; };
1011
05031BFA274EA93D00BB9A19 /* GetWebLinkSharedLink_VanityNameEnabled.json in Resources */ = {isa = PBXBuildFile; fileRef = 05031BF8274EA93D00BB9A19 /* GetWebLinkSharedLink_VanityNameEnabled.json */; };
1112
05070D2D2757DBD7000AFE20 /* BaseIntegrationSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05070D2C2757DBD7000AFE20 /* BaseIntegrationSpecs.swift */; };
1213
052BC90426F8AD09001E64D2 /* CommentsModuleSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8069D1DF22A84090006B5611 /* CommentsModuleSpecs.swift */; };
@@ -594,6 +595,7 @@
594595
/* End PBXCopyFilesBuildPhase section */
595596

596597
/* Begin PBXFileReference section */
598+
0501990B282423970085003B /* BoxClientIntegrationSpecs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxClientIntegrationSpecs.swift; sourceTree = "<group>"; };
597599
05031BF8274EA93D00BB9A19 /* GetWebLinkSharedLink_VanityNameEnabled.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GetWebLinkSharedLink_VanityNameEnabled.json; sourceTree = "<group>"; };
598600
05070D2C2757DBD7000AFE20 /* BaseIntegrationSpecs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseIntegrationSpecs.swift; sourceTree = "<group>"; };
599601
052D63C127182FA500C76281 /* CreateSignRequest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CreateSignRequest.json; sourceTree = "<group>"; };
@@ -1208,6 +1210,7 @@
12081210
05070D2C2757DBD7000AFE20 /* BaseIntegrationSpecs.swift */,
12091211
0579F6FF27577FD200473A3C /* FolderModuleIntegrationSpecs.swift */,
12101212
05EA725A27621FA7001ECFF3 /* FileModuleIntegrationSpecs.swift */,
1213+
0501990B282423970085003B /* BoxClientIntegrationSpecs.swift */,
12111214
);
12121215
path = IntegrationTests;
12131216
sourceTree = "<group>";
@@ -2740,6 +2743,7 @@
27402743
0579F70027577FD200473A3C /* FolderModuleIntegrationSpecs.swift in Sources */,
27412744
0547B743276C9A89002D9E7A /* FileUtil.swift in Sources */,
27422745
05EC1086276A1CFE00252112 /* Task+Extensions.swift in Sources */,
2746+
0501990C282423970085003B /* BoxClientIntegrationSpecs.swift in Sources */,
27432747
05070D2D2757DBD7000AFE20 /* BaseIntegrationSpecs.swift in Sources */,
27442748
);
27452749
runOnlyForDeploymentPostprocessing = 0;

IntegrationTests/BaseIntegrationSpecs.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,22 @@ class BaseIntegrationSpecs: QuickSpec {
172172
}
173173
}
174174
}
175+
176+
// MARK: WebLink helper methods
177+
178+
func deleteWebLink(_ webLink: WebLink?) {
179+
guard let webLink = webLink else {
180+
return
181+
}
182+
183+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
184+
self.client.webLinks.delete(webLinkId: webLink.id) { result in
185+
if case let .failure(error) = result {
186+
fail("Expected delete call to succeed, but instead got \(error)")
187+
}
188+
189+
done()
190+
}
191+
}
192+
}
175193
}
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
//
2+
// BoxClientIntegrationSpecs.swift
3+
// BoxSDKIntegrationTests-iOS
4+
//
5+
// Created by Artur Jankowski on 05/05/2022.
6+
// Copyright © 2022 box. All rights reserved.
7+
//
8+
9+
@testable import BoxSDK
10+
import Nimble
11+
import Quick
12+
13+
class BoxClientIntegrationSpecs: BaseIntegrationSpecs {
14+
var rootFolder: Folder!
15+
16+
override func spec() {
17+
beforeSuite {
18+
self.createFolder(name: NameGenerator.getUniqueFolderName(for: "BoxClient")) { [weak self] createdFolder in self?.rootFolder = createdFolder }
19+
}
20+
21+
afterSuite {
22+
self.deleteFolder(self.rootFolder)
23+
}
24+
25+
describe("BoxClient") {
26+
27+
context("Custom API calls") {
28+
29+
context("get()") {
30+
var file: File?
31+
32+
beforeEach {
33+
self.uploadFile(fileName: IntegrationTestResources.smallPdf.fileName, toFolder: self.rootFolder?.id) { uploadedFile in file = uploadedFile }
34+
}
35+
36+
afterEach {
37+
self.deleteFile(file)
38+
}
39+
40+
it("should make valid API call") {
41+
guard let file = file else {
42+
fail("An error occurred during setup initial data")
43+
return
44+
}
45+
46+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
47+
self.client.get(url: URL.boxAPIEndpoint("/2.0/files/\(file.id)", configuration: self.client.configuration)) { result in
48+
let fileResult: Result<File, BoxSDKError> = result.flatMap { ObjectDeserializer.deserialize(data: $0.body) }
49+
50+
switch fileResult {
51+
case let .success(fileItem):
52+
expect(fileItem).toNot(beNil())
53+
expect(fileItem.id).to(equal(file.id))
54+
expect(fileItem.name).to(equal(IntegrationTestResources.smallPdf.fileName))
55+
case let .failure(error):
56+
fail("Expected get call to succeed, but instead got \(error)")
57+
}
58+
done()
59+
}
60+
}
61+
}
62+
}
63+
64+
context("post()") {
65+
var webLink: WebLink?
66+
67+
afterEach {
68+
self.deleteWebLink(webLink)
69+
}
70+
71+
it("should make valid API call") {
72+
var body: [String: Any] = [:]
73+
body["parent"] = ["id": self.rootFolder.id]
74+
body["url"] = "https://example.com"
75+
body["name"] = "example name"
76+
77+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
78+
self.client.post(
79+
url: URL.boxAPIEndpoint("/2.0/web_links", configuration: self.client.configuration),
80+
json: body
81+
) { result in
82+
let webLinkResult: Result<WebLink, BoxSDKError> = result.flatMap { ObjectDeserializer.deserialize(data: $0.body) }
83+
84+
switch webLinkResult {
85+
case let .success(webLinkItem):
86+
webLink = webLinkItem
87+
expect(webLinkItem).toNot(beNil())
88+
expect(webLinkItem.name).to(equal("example name"))
89+
case let .failure(error):
90+
fail("Expected post call to succeed, but instead got \(error)")
91+
}
92+
done()
93+
}
94+
}
95+
}
96+
}
97+
98+
context("put()") {
99+
var file: File?
100+
let newFileName = "updatedName.pdf"
101+
let newDescription = "Sample description"
102+
103+
beforeEach {
104+
self.uploadFile(fileName: IntegrationTestResources.smallPdf.fileName, toFolder: self.rootFolder?.id) { uploadedFile in file = uploadedFile }
105+
}
106+
107+
afterEach {
108+
self.deleteFile(file)
109+
}
110+
111+
it("should make valid API call") {
112+
guard let file = file else {
113+
fail("An error occurred during setup initial data")
114+
return
115+
}
116+
117+
var body: [String: Any] = [:]
118+
body["name"] = newFileName
119+
body["description"] = newDescription
120+
121+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
122+
self.client.put(
123+
url: URL.boxAPIEndpoint("/2.0/files/\(file.id)", configuration: self.client.configuration),
124+
queryParameters: ["fields": "name,description"],
125+
json: body
126+
) { result in
127+
let fileResult: Result<File, BoxSDKError> = result.flatMap { ObjectDeserializer.deserialize(data: $0.body) }
128+
129+
switch fileResult {
130+
case let .success(fileItem):
131+
expect(fileItem).toNot(beNil())
132+
expect(fileItem.id).to(equal(file.id))
133+
expect(fileItem.name).to(equal(newFileName))
134+
expect(fileItem.description).to(equal(newDescription))
135+
case let .failure(error):
136+
fail("Expected put call to succeed, but instead got \(error)")
137+
}
138+
done()
139+
}
140+
}
141+
}
142+
}
143+
144+
context("delete()") {
145+
var file: File?
146+
147+
beforeEach {
148+
self.uploadFile(fileName: IntegrationTestResources.smallPdf.fileName, toFolder: self.rootFolder?.id) { uploadedFile in file = uploadedFile }
149+
}
150+
151+
it("should make valid API call") {
152+
guard let file = file else {
153+
fail("An error occurred during setup initial data")
154+
return
155+
}
156+
157+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
158+
self.client.delete(url: URL.boxAPIEndpoint("/2.0/files/\(file.id)", configuration: self.client.configuration)) { result in
159+
if case let .failure(error) = result {
160+
fail("Expected delete call to succeed, but instead got \(error)")
161+
}
162+
163+
done()
164+
}
165+
}
166+
}
167+
}
168+
169+
context("options()") {
170+
it("should make valid API call") {
171+
var body: [String: Any] = [:]
172+
body["parent"] = ["id": "\(self.rootFolder.id)"]
173+
body["name"] = "exampleName.txt"
174+
175+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
176+
self.client.options(
177+
url: URL.boxAPIEndpoint("/2.0/files/content", configuration: self.client.configuration),
178+
json: body
179+
) { result in
180+
if case let .failure(error) = result {
181+
fail("Expected options call to succeed, but instead got \(error)")
182+
}
183+
184+
done()
185+
}
186+
}
187+
}
188+
}
189+
190+
context("download()") {
191+
var file: File?
192+
193+
beforeEach {
194+
self.uploadFile(fileName: IntegrationTestResources.smallPdf.fileName, toFolder: self.rootFolder?.id) { uploadedFile in file = uploadedFile }
195+
}
196+
197+
afterEach {
198+
self.deleteFile(file)
199+
}
200+
201+
it("should make valid API call") {
202+
guard let file = file else {
203+
fail("An error occurred during setup initial data")
204+
return
205+
}
206+
207+
let fileContent = FileUtil.getFileContent(fileName: IntegrationTestResources.smallPdf.fileName)!
208+
let destinationURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(IntegrationTestResources.smallPdf.fileName)
209+
210+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
211+
self.client.download(
212+
url: URL.boxAPIEndpoint("/2.0/files/\(file.id)/content", configuration: self.client.configuration),
213+
downloadDestinationURL: destinationURL
214+
) { result in
215+
switch result {
216+
case .success:
217+
expect(FileManager().fileExists(atPath: destinationURL.path)).to(equal(true))
218+
219+
guard let downloadedContent = try? Data(contentsOf: destinationURL) else {
220+
fail("Can not read downloaded file")
221+
return
222+
}
223+
224+
expect(fileContent).to(equal(downloadedContent))
225+
case let .failure(error):
226+
fail("Expected download call to succeed, but instead got \(error)")
227+
}
228+
229+
done()
230+
}
231+
}
232+
}
233+
}
234+
235+
context("send()") {
236+
var file: File?
237+
let newFileName = "updatedName.pdf"
238+
let newDescription = "Sample description"
239+
240+
beforeEach {
241+
self.uploadFile(fileName: IntegrationTestResources.smallPdf.fileName, toFolder: self.rootFolder?.id) { uploadedFile in file = uploadedFile }
242+
}
243+
244+
afterEach {
245+
self.deleteFile(file)
246+
}
247+
248+
it("should make valid API call") {
249+
guard let file = file else {
250+
fail("An error occurred during setup initial data")
251+
return
252+
}
253+
254+
var body: [String: Any] = [:]
255+
body["name"] = newFileName
256+
body["description"] = newDescription
257+
258+
let request = BoxRequest(
259+
httpMethod: .put,
260+
url: URL.boxAPIEndpoint("/2.0/files/\(file.id)", configuration: self.client.configuration),
261+
queryParams: ["fields": "name,description"],
262+
body: .jsonObject(body)
263+
)
264+
265+
waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in
266+
self.client.send(request: request) { result in
267+
let fileResult: Result<File, BoxSDKError> = result.flatMap { ObjectDeserializer.deserialize(data: $0.body) }
268+
switch fileResult {
269+
case let .success(fileItem):
270+
expect(fileItem).toNot(beNil())
271+
expect(fileItem.id).to(equal(file.id))
272+
expect(fileItem.name).to(equal(newFileName))
273+
expect(fileItem.description).to(equal(newDescription))
274+
case let .failure(error):
275+
fail("Expected send call to succeed, but instead got \(error)")
276+
}
277+
done()
278+
}
279+
}
280+
}
281+
}
282+
}
283+
}
284+
}
285+
}

Sources/Client/BoxClient.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,14 @@ public class BoxClient {
135135
}
136136
}
137137

138-
private extension BoxClient {
139-
func send(
138+
extension BoxClient {
139+
140+
/// Makes a Box SDK request
141+
///
142+
/// - Parameters:
143+
/// - request: Box SDK request
144+
/// - completion: Returns standard BoxResponse object or error.
145+
public func send(
140146
request: BoxRequest,
141147
completion: @escaping Callback<BoxResponse>
142148
) {
@@ -169,7 +175,7 @@ private extension BoxClient {
169175
}
170176
}
171177

172-
func handleAuthIssues(
178+
private func handleAuthIssues(
173179
result: Result<BoxResponse, BoxSDKError>,
174180
completion: @escaping Callback<BoxResponse>
175181
) {
@@ -187,7 +193,7 @@ private extension BoxClient {
187193
}
188194
}
189195

190-
func addSharedLinkHeader(sharedLink: URL, sharedLinkPassword: String?) {
196+
private func addSharedLinkHeader(sharedLink: URL, sharedLinkPassword: String?) {
191197
if let sharedLinkPassword = sharedLinkPassword {
192198
headers?[BoxHTTPHeaderKey.boxApi] = "\(BoxAPIHeaderKey.sharedLink)=\(sharedLink.absoluteString)&\(BoxAPIHeaderKey.sharedLinkPassword)=\(sharedLinkPassword)"
193199
}
@@ -196,7 +202,7 @@ private extension BoxClient {
196202
}
197203
}
198204

199-
func addAsUserHeader(userId: String) {
205+
private func addAsUserHeader(userId: String) {
200206
headers?[BoxHTTPHeaderKey.asUser] = userId
201207
}
202208
}

0 commit comments

Comments
 (0)