diff --git a/Sources/NetworkImage/NetworkImageLoader.swift b/Sources/NetworkImage/NetworkImageLoader.swift index a491e6e..b07971b 100644 --- a/Sources/NetworkImage/NetworkImageLoader.swift +++ b/Sources/NetworkImage/NetworkImageLoader.swift @@ -18,7 +18,7 @@ public actor DefaultNetworkImageLoader { static let timeoutInterval: TimeInterval = 15 } - private let data: (URL) async throws -> (Data, URLResponse) + private let data: @Sendable (URL) async throws -> (Data, URLResponse) private let cache: NetworkImageCache private var ongoingTasks: [URL: Task] = [:] @@ -47,7 +47,7 @@ public actor DefaultNetworkImageLoader { init( cache: NetworkImageCache, - data: @escaping (URL) async throws -> (Data, URLResponse) + data: @escaping @Sendable (URL) async throws -> (Data, URLResponse) ) { self.data = data self.cache = cache @@ -70,9 +70,7 @@ extension DefaultNetworkImageLoader: NetworkImageLoader { // remove ongoing task self.ongoingTasks.removeValue(forKey: url) - guard let statusCode = (response as? HTTPURLResponse)?.statusCode, - 200..<300 ~= statusCode - else { + if let response = response as? HTTPURLResponse, !(200..<300).contains(response.statusCode) { throw URLError(.badServerResponse) } diff --git a/Tests/NetworkImageTests/DefaultNetworkImageLoaderTests.swift b/Tests/NetworkImageTests/DefaultNetworkImageLoaderTests.swift index d07858f..6fae8a2 100644 --- a/Tests/NetworkImageTests/DefaultNetworkImageLoaderTests.swift +++ b/Tests/NetworkImageTests/DefaultNetworkImageLoaderTests.swift @@ -1,15 +1,23 @@ import XCTest @testable import NetworkImage +#if canImport(AppKit) +import class AppKit.NSImage +#elseif canImport(UIKit) +import class UIKit.UIImage +#endif final class DefaultNetworkImageLoaderTests: XCTestCase { + @MainActor func testImageLoad() async throws { // given let imageCache = DefaultNetworkImageCache() var loadCount = 0 let imageLoader = DefaultNetworkImageLoader(cache: imageCache) { _ in - loadCount += 1 + Task { @MainActor in + loadCount += 1 + } return (Fixtures.imageData, Fixtures.okResponse) } @@ -27,6 +35,7 @@ final class DefaultNetworkImageLoaderTests: XCTestCase { XCTAssertIdentical(imageCache.image(for: Fixtures.anotherURL), images.1) } + @MainActor func testImageCache() async throws { // given let imageCache = DefaultNetworkImageCache() @@ -34,7 +43,9 @@ final class DefaultNetworkImageLoaderTests: XCTestCase { var loadCount = 0 let imageLoader = DefaultNetworkImageLoader(cache: imageCache) { _ in - loadCount += 1 + Task { @MainActor in + loadCount += 1 + } return (Fixtures.imageData, Fixtures.okResponse) } @@ -83,4 +94,36 @@ final class DefaultNetworkImageLoaderTests: XCTestCase { // then XCTAssertEqual(capturedError, URLError(.cannotDecodeContentData)) } + + func testLocalImageLoading() async throws { + // given + let fileManager = FileManager.default + let tmpDir = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try fileManager.createDirectory(at: tmpDir, withIntermediateDirectories: true) + defer { + try? fileManager.removeItem(at: tmpDir) + } + let localImageUrl = tmpDir.appendingPathComponent("image", conformingTo: .png) + try Fixtures.imageData.write(to: localImageUrl) + let imageLoader = DefaultNetworkImageLoader.shared + + // when + let image = try await imageLoader.image(from: localImageUrl) + + // then + try XCTAssertEqual(XCTUnwrap(image.pngData), XCTUnwrap(Fixtures.image.pngData)) + } +} + + +// MARK: Utils + +extension CGImage { + var pngData: Data? { + #if canImport(AppKit) + NSBitmapImageRep(cgImage: self).representation(using: .png, properties: [:]) + #elseif canImport(UIKit) + UIImage(cgImage: self).pngData() + #endif + } }