Compare commits
12 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
0be9d19396 | |
![]() |
ef89fdcbf6 | |
![]() |
838d43e66d | |
![]() |
4f31371f20 | |
![]() |
1c604afe9c | |
![]() |
bd8231252f | |
![]() |
d79ed6d6bc | |
![]() |
375187f613 | |
![]() |
38b15c9b8b | |
![]() |
f68cc90187 | |
![]() |
a42084f924 | |
![]() |
2368bb8d56 |
32
README.md
32
README.md
|
@ -2,6 +2,13 @@
|
|||
|
||||
WebDAV communication library for Swift
|
||||
|
||||
**Note**: This has only been tested on **Nextcloud** servers.
|
||||
Submit an [issue](https://github.com/Isvvc/WebDAV-Swift/issues) if you have compatibility issues with other WebDAV servers.
|
||||
Help in adding support for additional services would be greatly appreciated!
|
||||
See [Contribution](#contribution).
|
||||
|
||||
* [\[#43\]](https://github.com/Isvvc/WebDAV-Swift/issues/43) Apache WebDAV has been reported to not work
|
||||
|
||||
## Table of contents
|
||||
|
||||
+ [Install](#install)
|
||||
|
@ -182,6 +189,31 @@ Image functions include:
|
|||
_Why is there no `deleteCachedImage` or `cachedImageURL` function when there is `getCachedThumbnail` and `cachedThumbnailURL`?_
|
||||
Images are stored in the disk cache the same way as data. The image-specific functions exist as a convenience for converting the data to UIImages and caching them in memory that way. Since the cached data URL does not change whether the data is an image or not, `deleteCachedData` and `cachedDataURL` can be used for images.
|
||||
|
||||
#### Thumbnail preview
|
||||
|
||||
If there are already cached thumbnails for the image you are trying to fetch, you can use the `preview` parameter to specify that you would like to get that thumbnail first while the full-size image is downloading. When you do this, the completion closure will run with a `.placeholder` error on the call with the thumbnail.
|
||||
|
||||
```swift
|
||||
webDAV.downloadImage(path: imagePath, account: account, password: password, preview: .memoryOnly) { image, error in
|
||||
switch error {
|
||||
case .none, .placeholder:
|
||||
// .none is the full-size image.
|
||||
// .placeholder is the thumbnail.
|
||||
// The completion closure will not be run with the thumbnail after
|
||||
// it is run with the full-size image, so assuming you don't have
|
||||
// a use for the thumbnail after the full-size image loads, you
|
||||
// shouldn't need to check which it is before displaying.
|
||||
break
|
||||
case .some(let unexpectedError):
|
||||
// Log the error
|
||||
}
|
||||
|
||||
// Display the image
|
||||
}
|
||||
```
|
||||
|
||||
See [Thumbnails](#thumbnails) for more details on thumbnails.
|
||||
|
||||
### Thumbnails
|
||||
|
||||
Along with downloading full-sized images, you can download **thumbnails** from Nextcloud servers.
|
||||
|
|
|
@ -23,9 +23,16 @@ public extension WebDAV {
|
|||
func cachedDataURL<A: WebDAVAccount>(forItemAtPath path: String, account: A) -> URL? {
|
||||
guard let encodedDescription = UnwrappedAccount(account: account)?.encodedDescription,
|
||||
let caches = cacheFolder else { return nil }
|
||||
return caches
|
||||
.appendingPathComponent(encodedDescription)
|
||||
.appendingPathComponent(path.trimmingCharacters(in: AccountPath.slash))
|
||||
let trimmedPath = path.trimmingCharacters(in: AccountPath.slash)
|
||||
|
||||
if trimmedPath.isEmpty {
|
||||
return caches
|
||||
.appendingPathComponent(encodedDescription)
|
||||
} else {
|
||||
return caches
|
||||
.appendingPathComponent(encodedDescription)
|
||||
.appendingPathComponent(trimmedPath)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the local cached data URL for the item at the specified path if there is cached data there.
|
||||
|
@ -178,13 +185,14 @@ extension WebDAV {
|
|||
|
||||
func cleanupDiskCache<A: WebDAVAccount>(at path: String, account: A, files: [WebDAVFile]) throws {
|
||||
let fm = FileManager.default
|
||||
guard let url = cachedDataURL(forItemAtPath: path, account: account),fm.fileExists(atPath: url.path) else { return }
|
||||
guard let url = cachedDataURL(forItemAtPath: path, account: account),
|
||||
fm.fileExists(atPath: url.path) else { return }
|
||||
|
||||
let goodFilePaths = Set(files.compactMap { cachedDataURL(forItemAtPath: $0.path, account: account)?.path })
|
||||
let goodFilePaths = files.compactMap { cachedDataURL(forItemAtPath: $0.path, account: account)?.path }
|
||||
|
||||
let infoPlist = filesCacheURL?.path
|
||||
for path in try fm.contentsOfDirectory(atPath: url.path).map({ url.appendingPathComponent($0).path })
|
||||
where !goodFilePaths.contains(path)
|
||||
where !goodFilePaths.contains(where: { path.starts(with: $0) })
|
||||
&& path != infoPlist {
|
||||
try fm.removeItem(atPath: path)
|
||||
}
|
||||
|
|
|
@ -67,6 +67,16 @@ public struct ThumbnailProperties: Hashable {
|
|||
|
||||
public extension WebDAV {
|
||||
|
||||
enum ThumbnailPreviewMode {
|
||||
/// Only show a preview thumbnail if there is already one loaded into memory.
|
||||
case memoryOnly
|
||||
/// Allow the disk cache to be loaded if there are no thumbnails in memory.
|
||||
/// Note that this can be an expensive process and is run on the main thread.
|
||||
case diskAllowed
|
||||
/// Load the specific thumbnail if available, from disk if not in memory.
|
||||
case specific(ThumbnailProperties)
|
||||
}
|
||||
|
||||
//MARK: Images
|
||||
|
||||
/// Download and cache an image from the specified file path.
|
||||
|
@ -75,16 +85,40 @@ public extension WebDAV {
|
|||
/// - account: The WebDAV account.
|
||||
/// - password: The WebDAV account's password.
|
||||
/// - options: Options for caching the results. Empty set uses default caching behavior.
|
||||
/// - completion: If account properties are invalid, this will run immediately on the same thread.
|
||||
/// Otherwise, it runs when the network call finishes on a background thread.
|
||||
/// - preview: Behavior for running the completion closure with cached thumbnails before the full-sized image is fetched.
|
||||
/// Note that `.diskAllowed` will load all thumbnails for the given image which can be an expensive process.
|
||||
/// `.memoryOnly` and `.specific()` are recommended unless you do not know what thumbnails exist.
|
||||
/// - completion: If account properties are invalid, this will run immediately on the same thread with an error.
|
||||
/// Otherwise, it will run on a utility thread with a preview (if available and a `preview` mode is provided) with a `.placeholder` error,
|
||||
/// then run on a background thread when the network call finishes.
|
||||
/// This will not be called with the thumbnail after being called with the full-size image.
|
||||
/// - image: The image downloaded, if successful.
|
||||
/// The cached image if it has already been downloaded.
|
||||
/// - cachedImageURL: The URL of the cached image.
|
||||
/// - error: A WebDAVError if the call was unsuccessful. `nil` if it was.
|
||||
/// - Returns: The request identifier.
|
||||
@discardableResult
|
||||
func downloadImage<A: WebDAVAccount>(path: String, account: A, password: String, caching options: WebDAVCachingOptions = [], completion: @escaping (_ image: UIImage?, _ error: WebDAVError?) -> Void) -> URLSessionDataTask? {
|
||||
cachingDataTask(cache: imageCache, path: path, account: account, password: password, caching: options, valueFromData: { UIImage(data: $0) }, completion: completion)
|
||||
func downloadImage<A: WebDAVAccount>(path: String, account: A, password: String, caching options: WebDAVCachingOptions = [], preview: ThumbnailPreviewMode? = .none, completion: @escaping (_ image: UIImage?, _ error: WebDAVError?) -> Void) -> URLSessionDataTask? {
|
||||
cachingDataTask(cache: imageCache, path: path, account: account, password: password, caching: options, valueFromData: { UIImage(data: $0) }, placeholder: {
|
||||
// Load placeholder thumbnail
|
||||
var thumbnails = self.getAllMemoryCachedThumbnails(forItemAtPath: path, account: account)?.values
|
||||
|
||||
switch preview {
|
||||
case .none:
|
||||
return nil
|
||||
case .specific(let properties):
|
||||
return self.getCachedThumbnail(forItemAtPath: path, account: account, with: properties)
|
||||
case .memoryOnly:
|
||||
break
|
||||
case .diskAllowed:
|
||||
// Only load from disk if there aren't any in memory
|
||||
if thumbnails?.isEmpty ?? true {
|
||||
thumbnails = self.getAllMemoryCachedThumbnails(forItemAtPath: path, account: account)?.values
|
||||
}
|
||||
}
|
||||
let largestThumbnail = thumbnails?.max(by: { $0.size.width * $0.size.height < $1.size.width * $1.size.height })
|
||||
return largestThumbnail
|
||||
}, completion: completion)
|
||||
}
|
||||
|
||||
//MARK: Thumbnails
|
||||
|
|
|
@ -384,7 +384,10 @@ extension WebDAV {
|
|||
|
||||
//MARK: Standard Requests
|
||||
|
||||
func cachingDataTask<A: WebDAVAccount, Value: Equatable>(cache: Cache<AccountPath, Value>, path: String, account: A, password: String, caching options: WebDAVCachingOptions, valueFromData: @escaping (_ data: Data) -> Value?, completion: @escaping (_ value: Value?, _ error: WebDAVError?) -> Void) -> URLSessionDataTask? {
|
||||
func cachingDataTask<A: WebDAVAccount, Value: Equatable>(
|
||||
cache: Cache<AccountPath, Value>, path: String, account: A, password: String,
|
||||
caching options: WebDAVCachingOptions, valueFromData: @escaping (_ data: Data) -> Value?, placeholder: (() -> Value?)? = nil,
|
||||
completion: @escaping (_ value: Value?, _ error: WebDAVError?) -> Void) -> URLSessionDataTask? {
|
||||
|
||||
// Check cache
|
||||
|
||||
|
@ -407,10 +410,19 @@ extension WebDAV {
|
|||
}
|
||||
}
|
||||
|
||||
// Cached data was not returned. Continue with network fetch.
|
||||
|
||||
if options.contains(.removeExistingCache) {
|
||||
try? deleteCachedData(forItemAtPath: path, account: account)
|
||||
}
|
||||
|
||||
let placeholderTask = DispatchWorkItem {
|
||||
if let placeholderValue = placeholder?() {
|
||||
completion(placeholderValue, .placeholder)
|
||||
}
|
||||
}
|
||||
DispatchQueue.global(qos: .utility).async(execute: placeholderTask)
|
||||
|
||||
// Create network request
|
||||
|
||||
guard let request = authorizedRequest(path: path, account: account, password: password, method: .get) else {
|
||||
|
@ -427,6 +439,7 @@ extension WebDAV {
|
|||
return completion(nil, error)
|
||||
} else if let data = data,
|
||||
let value = valueFromData(data) {
|
||||
placeholderTask.cancel()
|
||||
// Cache result
|
||||
if !options.contains(.removeExistingCache),
|
||||
!options.contains(.doNotCacheResult) {
|
||||
|
@ -528,7 +541,7 @@ extension WebDAV {
|
|||
for (key, _) in filesCache
|
||||
where key.path != directory
|
||||
&& key.path.starts(with: directory)
|
||||
&& !files.contains(where: { key.path.starts(with: $0.path) }) {
|
||||
&& !files.contains(where: { key.path.starts(with: $0.path.trimmingCharacters(in: AccountPath.slash)) }) {
|
||||
filesCache.removeValue(forKey: key)
|
||||
changed = true
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ public enum WebDAVError: Error {
|
|||
case unsupported
|
||||
/// Another unspecified Error occurred.
|
||||
case nsError(Error)
|
||||
/// The returned value is simply a placeholder.
|
||||
case placeholder
|
||||
|
||||
static func getError(statusCode: Int?, error: Error?) -> WebDAVError? {
|
||||
if let statusCode = statusCode {
|
||||
|
|
|
@ -20,7 +20,7 @@ public struct WebDAVFile: Identifiable, Codable, Equatable, Hashable {
|
|||
public private(set) var size: Int
|
||||
public private(set) var etag: String
|
||||
|
||||
init(path: String, id: String, isDirectory: Bool, lastModified: Date, size: Int, etag: String) {
|
||||
public init(path: String, id: String, isDirectory: Bool, lastModified: Date, size: Int, etag: String) {
|
||||
self.path = path
|
||||
self.id = id
|
||||
self.isDirectory = isDirectory
|
||||
|
|
|
@ -356,29 +356,46 @@ final class WebDAVTests: XCTestCase {
|
|||
func testCleanupFilesCacheRoot() {
|
||||
guard let (account, password) = getAccount() else { return XCTFail() }
|
||||
|
||||
let listRealDirExpectation = XCTestExpectation(description: "List files from real directory.")
|
||||
let expectation = XCTestExpectation(description: "List files from WebDAV")
|
||||
|
||||
let path = UUID().uuidString
|
||||
let accountPath = AccountPath(account: account, path: path)
|
||||
let realDir = createFolder(account: account, password: password)
|
||||
let realDirAccountPath = AccountPath(account: account, path: realDir)
|
||||
|
||||
let fakeDir = UUID().uuidString
|
||||
let fakeDirAccountPath = AccountPath(account: account, path: fakeDir)
|
||||
|
||||
// Load real file into cache
|
||||
uploadData(to: realDir, account: account, password: password)
|
||||
webDAV.listFiles(atPath: realDir, account: account, password: password, caching: .doNotReturnCachedResult) { _, _ in
|
||||
listRealDirExpectation.fulfill()
|
||||
}
|
||||
|
||||
wait(for: [listRealDirExpectation], timeout: 10000.0)
|
||||
|
||||
XCTAssertNotNil(webDAV.filesCache[realDirAccountPath])
|
||||
|
||||
// Place fake cache
|
||||
|
||||
webDAV.filesCache[accountPath] = [WebDAVFile(path: path + "/fake.txt", id: "0", isDirectory: true, lastModified: Date(), size: 0, etag: "0")]
|
||||
XCTAssertNotNil(webDAV.filesCache[accountPath])
|
||||
webDAV.filesCache[fakeDirAccountPath] = [WebDAVFile(path: fakeDir + "/fake.txt", id: "0", isDirectory: true, lastModified: Date(), size: 0, etag: "0")]
|
||||
XCTAssertNotNil(webDAV.filesCache[fakeDirAccountPath])
|
||||
|
||||
// List files
|
||||
|
||||
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
|
||||
webDAV.listFiles(atPath: "/", account: account, password: password, caching: .doNotReturnCachedResult) { files, error in
|
||||
XCTAssertNotNil(files)
|
||||
XCTAssertNil(error)
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
wait(for: [expectation], timeout: 10.0)
|
||||
wait(for: [expectation], timeout: 10000.0)
|
||||
|
||||
// Check that the fake cached file was cleaned up
|
||||
XCTAssertNil(webDAV.filesCache[fakeDirAccountPath])
|
||||
// Check that the real file still exists
|
||||
XCTAssertNotNil(webDAV.filesCache[realDirAccountPath])
|
||||
|
||||
XCTAssertNil(webDAV.filesCache[accountPath])
|
||||
deleteFile(path: realDir, account: account, password: password)
|
||||
}
|
||||
|
||||
func testCleanupFilesCacheSubdirectory() {
|
||||
|
@ -397,7 +414,7 @@ final class WebDAVTests: XCTestCase {
|
|||
|
||||
// List files
|
||||
|
||||
webDAV.listFiles(atPath: folder, account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
|
||||
webDAV.listFiles(atPath: folder, account: account, password: password, foldersFirst: false, caching: .doNotReturnCachedResult) { files, error in
|
||||
XCTAssertNotNil(files)
|
||||
XCTAssertNil(error)
|
||||
expectation.fulfill()
|
||||
|
@ -413,23 +430,31 @@ final class WebDAVTests: XCTestCase {
|
|||
|
||||
//MARK: Disk Cache Cleanup
|
||||
|
||||
func testCleanupDiskCacheFile() {
|
||||
func testCleanupDiskCacheFileRoot() {
|
||||
guard let (account, password) = getAccount() else { return XCTFail() }
|
||||
|
||||
let expectation = XCTestExpectation(description: "List files from WebDAV")
|
||||
|
||||
// Add dummy file to disk cache
|
||||
|
||||
let path = UUID().uuidString + ".txt"
|
||||
let dummyPath = UUID().uuidString + ".txt"
|
||||
let data = UUID().uuidString.data(using: .utf8)!
|
||||
let tempFileURL = webDAV.cachedDataURL(forItemAtPath: path, account: account)!
|
||||
XCTAssertNoThrow(try webDAV.saveDataToDiskCache(data, url: tempFileURL))
|
||||
let dummyFileURL = webDAV.cachedDataURL(forItemAtPath: dummyPath, account: account)!
|
||||
XCTAssertNoThrow(try webDAV.saveDataToDiskCache(data, url: dummyFileURL))
|
||||
|
||||
XCTAssert(FileManager.default.fileExists(atPath: tempFileURL.path))
|
||||
XCTAssert(FileManager.default.fileExists(atPath: dummyFileURL.path))
|
||||
|
||||
// Create real file
|
||||
|
||||
let realFile = uploadData(account: account, password: password)
|
||||
let realFileURL = webDAV.cachedDataURL(forItemAtPath: realFile.fileName, account: account)!
|
||||
downloadData(path: realFile.fileName, account: account, password: password)
|
||||
|
||||
XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))
|
||||
|
||||
// List files
|
||||
|
||||
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
|
||||
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .doNotReturnCachedResult) { files, error in
|
||||
XCTAssertNotNil(files)
|
||||
XCTAssertNil(error)
|
||||
expectation.fulfill()
|
||||
|
@ -438,8 +463,11 @@ final class WebDAVTests: XCTestCase {
|
|||
wait(for: [expectation], timeout: 10.0)
|
||||
|
||||
// Check that the fake cached file was cleaned up
|
||||
XCTAssertFalse(FileManager.default.fileExists(atPath: dummyFileURL.path))
|
||||
// Check that the real file still exists
|
||||
XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))
|
||||
|
||||
XCTAssertFalse(FileManager.default.fileExists(atPath: tempFileURL.path))
|
||||
deleteFile(path: realFile.fileName, account: account, password: password)
|
||||
}
|
||||
|
||||
func testCleanupDiskCacheFolder() {
|
||||
|
@ -450,13 +478,23 @@ final class WebDAVTests: XCTestCase {
|
|||
// Add dummy folder to disk cache
|
||||
|
||||
let path = UUID().uuidString
|
||||
let tempFileURL = webDAV.cachedDataURL(forItemAtPath: path, account: account)!
|
||||
XCTAssertNoThrow(try FileManager.default.createDirectory(at: tempFileURL, withIntermediateDirectories: true))
|
||||
XCTAssert(FileManager.default.fileExists(atPath: tempFileURL.path))
|
||||
let dummyFileURL = webDAV.cachedDataURL(forItemAtPath: path, account: account)!
|
||||
XCTAssertNoThrow(try FileManager.default.createDirectory(at: dummyFileURL, withIntermediateDirectories: true))
|
||||
|
||||
XCTAssert(FileManager.default.fileExists(atPath: dummyFileURL.path))
|
||||
|
||||
// Create real folder
|
||||
|
||||
let folder = createFolder(account: account, password: password)
|
||||
let realFile = uploadData(to: folder, account: account, password: password)
|
||||
downloadData(path: realFile.fileName, account: account, password: password)
|
||||
let realFileURL = webDAV.cachedDataURL(forItemAtPath: realFile.fileName, account: account)!
|
||||
|
||||
XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))
|
||||
|
||||
// List files
|
||||
|
||||
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
|
||||
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .doNotReturnCachedResult) { files, error in
|
||||
XCTAssertNotNil(files)
|
||||
XCTAssertNil(error)
|
||||
expectation.fulfill()
|
||||
|
@ -465,8 +503,11 @@ final class WebDAVTests: XCTestCase {
|
|||
wait(for: [expectation], timeout: 10.0)
|
||||
|
||||
// Check that the fake cached folder was cleaned up
|
||||
XCTAssertFalse(FileManager.default.fileExists(atPath: dummyFileURL.path))
|
||||
// Check that the real file still exists
|
||||
XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))
|
||||
|
||||
XCTAssertFalse(FileManager.default.fileExists(atPath: tempFileURL.path))
|
||||
deleteFile(path: folder, account: account, password: password)
|
||||
}
|
||||
|
||||
func testCleanupDiskCacheWithGoodFile() {
|
||||
|
@ -496,7 +537,7 @@ final class WebDAVTests: XCTestCase {
|
|||
|
||||
// List files
|
||||
|
||||
webDAV.listFiles(atPath: directory.path, account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
|
||||
webDAV.listFiles(atPath: directory.path, account: account, password: password, caching: .doNotReturnCachedResult) { files, error in
|
||||
XCTAssertNotNil(files)
|
||||
XCTAssertNil(error)
|
||||
expectation.fulfill()
|
||||
|
@ -511,7 +552,35 @@ final class WebDAVTests: XCTestCase {
|
|||
XCTAssertNoThrow(try webDAV.deleteCachedData(forItemAtPath: imagePath, account: account))
|
||||
}
|
||||
|
||||
//MARK: Image Cache
|
||||
func testCleanupDiskCacheKeepingThumbnail() {
|
||||
guard let (account, password) = getAccount() else { return XCTFail() }
|
||||
guard let imagePath = ProcessInfo.processInfo.environment["image_path"] else {
|
||||
return XCTFail("You need to set the image_path in the environment.")
|
||||
}
|
||||
|
||||
let expectation = XCTestExpectation(description: "List files from WebDAV")
|
||||
|
||||
// Download Thumbnail
|
||||
downloadThumbnail(imagePath: imagePath, account: account, password: password)
|
||||
let cachedThumbnailURL = webDAV.cachedThumbnailURL(forItemAtPath: imagePath, account: account, with: .default)!
|
||||
XCTAssert(FileManager.default.fileExists(atPath: cachedThumbnailURL.path))
|
||||
|
||||
// List files
|
||||
|
||||
let imageURL = URL(fileURLWithPath: imagePath, isDirectory: false)
|
||||
let directory = imageURL.deletingLastPathComponent()
|
||||
|
||||
webDAV.listFiles(atPath: directory.path, account: account, password: password, caching: .doNotReturnCachedResult) { _, _ in
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
wait(for: [expectation], timeout: 10.0)
|
||||
|
||||
// Check that the cached thumbnail still exists
|
||||
XCTAssert(FileManager.default.fileExists(atPath: cachedThumbnailURL.path))
|
||||
}
|
||||
|
||||
//MARK: Images
|
||||
|
||||
func testDownloadImage() {
|
||||
guard let (account, password) = getAccount() else { return XCTFail() }
|
||||
|
@ -628,6 +697,34 @@ final class WebDAVTests: XCTestCase {
|
|||
XCTAssertFalse(FileManager.default.fileExists(atPath: cachedThumbnailFitURL.path))
|
||||
}
|
||||
|
||||
func testThumbnailPlaceholder() {
|
||||
guard let (account, password) = getAccount() else { return XCTFail() }
|
||||
guard let imagePath = ProcessInfo.processInfo.environment["image_path"] else {
|
||||
return XCTFail("You need to set the image_path in the environment.")
|
||||
}
|
||||
|
||||
let thumbnailExpectation = XCTestExpectation(description: "Get the cached thumbnail")
|
||||
let imageExpectation = XCTestExpectation(description: "Fetch image")
|
||||
|
||||
downloadThumbnail(imagePath: imagePath, account: account, password: password)
|
||||
|
||||
try? webDAV.deleteCachedData(forItemAtPath: imagePath, account: account)
|
||||
webDAV.downloadImage(path: imagePath, account: account, password: password, preview: .memoryOnly) { image, error in
|
||||
switch error {
|
||||
case .placeholder:
|
||||
thumbnailExpectation.fulfill()
|
||||
case .none:
|
||||
imageExpectation.fulfill()
|
||||
case .some(let unexpectedError):
|
||||
XCTFail("\(unexpectedError)")
|
||||
}
|
||||
XCTAssertNotNil(image)
|
||||
}
|
||||
try? webDAV.deleteCachedData(forItemAtPath: imagePath, account: account)
|
||||
|
||||
wait(for: [thumbnailExpectation, imageExpectation], timeout: 10.0)
|
||||
}
|
||||
|
||||
//MARK: OCS
|
||||
|
||||
func testColorHex() {
|
||||
|
@ -691,11 +788,17 @@ final class WebDAVTests: XCTestCase {
|
|||
wait(for: [expectation], timeout: 10.0)
|
||||
}
|
||||
|
||||
private func uploadData(account: SimpleAccount, password: String) -> (name: String, fileName: String, content: String) {
|
||||
@discardableResult
|
||||
private func uploadData(to folder: String = "", account: SimpleAccount, password: String) -> (name: String, fileName: String, content: String) {
|
||||
let expectation = XCTestExpectation(description: "Upload data")
|
||||
|
||||
let name = UUID().uuidString
|
||||
let fileName = name + ".txt"
|
||||
let fileName: String
|
||||
if folder.isEmpty {
|
||||
fileName = name + ".txt"
|
||||
} else {
|
||||
fileName = "\(folder)/\(name).txt"
|
||||
}
|
||||
let content = UUID().uuidString
|
||||
let data = content.data(using: .utf8)!
|
||||
|
||||
|
@ -735,6 +838,21 @@ final class WebDAVTests: XCTestCase {
|
|||
return folder
|
||||
}
|
||||
|
||||
private func downloadData(path file: String, account: SimpleAccount, password: String) {
|
||||
let expectation = XCTestExpectation(description: "Download file from WebDAV")
|
||||
|
||||
try? webDAV.deleteCachedData(forItemAtPath: file, account: account)
|
||||
|
||||
webDAV.download(fileAtPath: file, account: account, password: password) { image, error in
|
||||
XCTAssertNil(error)
|
||||
XCTAssertNotNil(image)
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
wait(for: [expectation], timeout: 10.0)
|
||||
}
|
||||
|
||||
private func downloadImage(imagePath: String, account: SimpleAccount, password: String) {
|
||||
let expectation = XCTestExpectation(description: "Download image from WebDAV")
|
||||
|
||||
|
@ -788,7 +906,7 @@ final class WebDAVTests: XCTestCase {
|
|||
("testCleanupFilesCacheRoot", testCleanupFilesCacheRoot),
|
||||
("testCleanupFilesCacheSubdirectory", testCleanupFilesCacheSubdirectory),
|
||||
// Disk Cache Cleanup
|
||||
("testCleanupDiskCacheFile", testCleanupDiskCacheFile),
|
||||
("testCleanupDiskCacheFileRoot", testCleanupDiskCacheFileRoot),
|
||||
("testCleanupDiskCacheFolder", testCleanupDiskCacheFolder),
|
||||
("testCleanupDiskCacheWithGoodFile", testCleanupDiskCacheWithGoodFile),
|
||||
// Image Cache
|
||||
|
@ -800,6 +918,7 @@ final class WebDAVTests: XCTestCase {
|
|||
("testThumbnailCacheURL", testThumbnailCacheURL),
|
||||
("testSpecificThumbnailCache", testSpecificThumbnailCache),
|
||||
("testGeneralThumbnailCache", testGeneralThumbnailCache),
|
||||
("testThumbnailPlaceholder", testThumbnailPlaceholder),
|
||||
// OCS
|
||||
("testTheme", testTheme),
|
||||
("testColorHex", testColorHex)
|
||||
|
|
Loading…
Reference in New Issue