diff --git a/.swiftlint.yml b/.swiftlint.yml index a68a2ed7f..56ceb34b1 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -117,8 +117,6 @@ identifier_name: - id - by -empty_count: warning - trailing_whitespace: ignores_empty_lines: no diff --git a/IntegrationTests/Base/QuickSpec+RetentionPolicies.swift b/IntegrationTests/Base/QuickSpec+RetentionPolicies.swift index 52fad789f..3d35aa9e6 100644 --- a/IntegrationTests/Base/QuickSpec+RetentionPolicies.swift +++ b/IntegrationTests/Base/QuickSpec+RetentionPolicies.swift @@ -18,6 +18,7 @@ extension QuickSpec { type: RetentionPolicyType = .finite, length: Int? = 1, dispositionAction: DispositionAction = .permanentlyDelete, + canOwnerExtendRetention: Bool = false, callback: @escaping (RetentionPolicy) -> Void ) { waitUntil(timeout: .seconds(Constants.Timeout.default)) { done in @@ -25,7 +26,8 @@ extension QuickSpec { name: name, type: type, length: length, - dispositionAction: dispositionAction + dispositionAction: dispositionAction, + canOwnerExtendRetention: canOwnerExtendRetention ) { result in switch result { case let .success(retention): diff --git a/IntegrationTests/FileModuleIntegrationSpecs.swift b/IntegrationTests/FileModuleIntegrationSpecs.swift index 29a1dc95d..1d588778d 100644 --- a/IntegrationTests/FileModuleIntegrationSpecs.swift +++ b/IntegrationTests/FileModuleIntegrationSpecs.swift @@ -483,7 +483,7 @@ class FileModuleIntegrationSpecs: QuickSpec { beforeEach { createFolder(client: client, name: NameGenerator.getUniqueFolderName(), parentId: rootFolder.id) { createdFolder in folder = createdFolder } - createRetention(client: client, name: NameGenerator.getUniqueName(for: "retention")) { createdRetention in retentionPolicy = createdRetention } + createRetention(client: client, name: NameGenerator.getUniqueName(for: "retention"), canOwnerExtendRetention: true) { createdRetention in retentionPolicy = createdRetention } assignRetention(client: client, retention: retentionPolicy, assignedContentId: folder?.id) { _ in } uploadFile(client: client, fileName: IntegrationTestResources.smallPdf.fileName, toFolder: folder?.id) { uploadedFile in file = uploadedFile } } diff --git a/Sources/Core/BoxJSONDecoder.swift b/Sources/Core/BoxJSONDecoder.swift index 6f16ff7ae..9042c62da 100644 --- a/Sources/Core/BoxJSONDecoder.swift +++ b/Sources/Core/BoxJSONDecoder.swift @@ -8,8 +8,7 @@ import Foundation -// swiftlint:disable:next convenience_type -class BoxJSONDecoder { +enum BoxJSONDecoder { static func extractJSON(json: [String: Any], key: String) throws -> T { guard let objectJSON = json[key] else { @@ -144,10 +143,18 @@ class BoxJSONDecoder { return nil } + #if compiler(>=5.9) + if #available(iOS 17.0, *) { + guard let url = URL(string: value, encodingInvalidCharacters: false) else { + throw BoxCodingError(message: .invalidValueFormat(key: key)) + } + return url + } + #endif + guard let url = URL(string: value) else { throw BoxCodingError(message: .invalidValueFormat(key: key)) } - return url } diff --git a/Sources/Requests/AnalyticsHeaderGenerator.swift b/Sources/Requests/AnalyticsHeaderGenerator.swift index 4dd1acce6..db730d617 100644 --- a/Sources/Requests/AnalyticsHeaderGenerator.swift +++ b/Sources/Requests/AnalyticsHeaderGenerator.swift @@ -40,6 +40,8 @@ class AnalyticsHeaderGenerator { return WKInterfaceDevice.current().model #elseif os(OSX) return "macOS" + #elseif os(visionOS) + return "visionOS" #endif }() @@ -48,7 +50,7 @@ class AnalyticsHeaderGenerator { return UIDevice.current.systemVersion #elseif os(watchOS) return WKInterfaceDevice.current().systemVersion - #elseif os(OSX) + #elseif os(OSX) || os(visionOS) let version = ProcessInfo.processInfo.operatingSystemVersion let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)" return versionString diff --git a/Tests/Helpers/OHTTPStubs+JSONComparer.swift b/Tests/Helpers/OHTTPStubs+JSONComparer.swift index c16e8299a..805354399 100644 --- a/Tests/Helpers/OHTTPStubs+JSONComparer.swift +++ b/Tests/Helpers/OHTTPStubs+JSONComparer.swift @@ -60,4 +60,27 @@ public extension QuickSpec { return match } } + + static func compareComplexQueryParam(_ key: String, _ partValues: [String], checkClosure _: CheckClosureType? = nil) -> HTTPStubsTestBlock { + return { req in + if let url = req.url { + let comps = NSURLComponents(url: url, resolvingAgainstBaseURL: true) + guard let queryItems = comps?.queryItems else { + return false + } + + guard let item = queryItems.first(where: { $0.name == key }) else { + return false + } + + guard let value = item.value else { + return false + } + + return partValues.allSatisfy { value.contains($0) } + } + + return false + } + } } diff --git a/Tests/Modules/FilesModuleSpecs.swift b/Tests/Modules/FilesModuleSpecs.swift index f1483a56b..80d2571f9 100644 --- a/Tests/Modules/FilesModuleSpecs.swift +++ b/Tests/Modules/FilesModuleSpecs.swift @@ -626,7 +626,7 @@ class FilesModuleSpecs: QuickSpec { waitUntil(timeout: .seconds(200)) { done in let data = "This is upload test file content".data(using: .utf8)! - var progressed: Double? + var progressed: Double? = 0 let task = sut.files.upload( data: data, name: "tigers.jpeg", @@ -667,7 +667,7 @@ class FilesModuleSpecs: QuickSpec { waitUntil(timeout: .seconds(200)) { done in let data = "This is upload test file content".data(using: .utf8)! - var progressed: Double? + var progressed: Double? = 0 var task: BoxUploadTask? task = sut.files.upload( data: data, @@ -1657,7 +1657,7 @@ class FilesModuleSpecs: QuickSpec { waitUntil(timeout: .seconds(10)) { done in let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let fileURL = documentsURL.appendingPathComponent("doc.txt") - var progressed: Double? + var progressed: Double? = 0 let task = sut.files.download( fileId: "12345", destinationURL: fileURL, @@ -1670,7 +1670,7 @@ class FilesModuleSpecs: QuickSpec { case .success: fail("Expected download to be cancelled, but instead suceeded") case let .failure(error): - expect(progressed).to(equal(0.05)) + expect(progressed).to(beLessThan(1.0)) expect(error.message.description).to(equal("cancelled")) } done() diff --git a/Tests/Modules/SearchModuleSpecs.swift b/Tests/Modules/SearchModuleSpecs.swift index 34d9c7e7d..f80b08324 100644 --- a/Tests/Modules/SearchModuleSpecs.swift +++ b/Tests/Modules/SearchModuleSpecs.swift @@ -69,7 +69,10 @@ class SearchModuleSpecs: QuickSpec { stub( condition: isHost("api.box.com") && isPath("/2.0/search") - && containsQueryParams(["mdfilters": "[{\"scope\":\"global\",\"templateKey\":\"marketingCollateral\",\"filters\":{\"date\":{\"gt\":\"2019-07-24T12:00:00Z\"}}}]"]) + && compareComplexQueryParam("mdfilters", ["\"filters\":{\"date\":{\"gt\":\"2019-07-24T12:00:00Z\"}}", + "\"templateKey\":\"marketingCollateral\"", + "\"scope\":\"global\"" + ]) ) { _ in HTTPStubsResponse( fileAtPath: TestAssets.path(forResource: "Search200.json")!, @@ -97,7 +100,10 @@ class SearchModuleSpecs: QuickSpec { stub( condition: isHost("api.box.com") && isPath("/2.0/search") - && containsQueryParams(["mdfilters": "[{\"scope\":\"enterprise\",\"templateKey\":\"marketingCollateral\",\"filters\":{\"date\":{\"lt\":\"2019-07-24T12:00:00Z\"}}}]"]) + && compareComplexQueryParam("mdfilters", ["\"filters\":{\"date\":{\"lt\":\"2019-07-24T12:00:00Z\"}}", + "\"templateKey\":\"marketingCollateral\"", + "\"scope\":\"enterprise\"" + ]) ) { _ in HTTPStubsResponse( fileAtPath: TestAssets.path(forResource: "Search200.json")!, @@ -125,7 +131,10 @@ class SearchModuleSpecs: QuickSpec { stub( condition: isHost("api.box.com") && isPath("/2.0/search") - && containsQueryParams(["mdfilters": "[{\"scope\":\"enterprise\",\"templateKey\":\"marketingCollateral\",\"filters\":{\"documentType\":\"dataSheet\"}}]"]) + && compareComplexQueryParam("mdfilters", ["\"filters\":{\"documentType\":\"dataSheet\"}", + "\"templateKey\":\"marketingCollateral\"", + "\"scope\":\"enterprise\"" + ]) ) { _ in HTTPStubsResponse( fileAtPath: TestAssets.path(forResource: "Search200.json")!, @@ -153,7 +162,10 @@ class SearchModuleSpecs: QuickSpec { stub( condition: isHost("api.box.com") && isPath("/2.0/search") - && containsQueryParams(["mdfilters": "[{\"scope\":\"global\",\"templateKey\":\"marketingCollateral\",\"filters\":{\"documentType\":\"dataSheet\"}}]"]) + && compareComplexQueryParam("mdfilters", ["\"filters\":{\"documentType\":\"dataSheet\"}", + "\"templateKey\":\"marketingCollateral\"", + "\"scope\":\"global\"" + ]) ) { _ in HTTPStubsResponse( fileAtPath: TestAssets.path(forResource: "Search200.json")!,