import XCTest import SwiftUI import ViewInspector @testable import SDWebImageSwiftUI extension WebImage : Inspectable {} class WebImageTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testWebImageWithStaticURL() throws { let expectation = self.expectation(description: "WebImage static url initializer") let imageUrl = URL(string: "https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png") let imageView = WebImage(url: imageUrl) let introspectView = imageView.onSuccess { image, data, cacheType in #if os(macOS) let displayImage = try? imageView.inspect().zStack().image(0).actualImage().nsImage() #else let displayImage = try? imageView.inspect().zStack().image(0).actualImage().cgImage() #endif XCTAssertNotNil(displayImage) expectation.fulfill() }.onFailure { error in XCTFail(error.localizedDescription) } _ = try introspectView.inspect() ViewHosting.host(view: introspectView) self.waitForExpectations(timeout: 5, handler: nil) ViewHosting.expel() } func testWebImageWithAnimatedURL() throws { let expectation = self.expectation(description: "WebImage animated url initializer") let imageUrl = URL(string: "https://apng.onevcat.com/assets/elephant.png") let binding = Binding(wrappedValue: true) let imageView = WebImage(url: imageUrl, isAnimating: binding) let introspectView = imageView.onSuccess { image, data, cacheType in if let animatedImage = image as? SDAnimatedImage { XCTAssertTrue(imageView.isAnimating) #if os(macOS) let displayImage = try? imageView.inspect().zStack().image(0).actualImage().nsImage() let size = displayImage?.size #else let displayImage = try? imageView.inspect().zStack().image(0).actualImage().cgImage() let size = CGSize(width: displayImage?.width ?? 0, height: displayImage?.height ?? 0) #endif XCTAssertNotNil(displayImage) // Check display image should match the animated poster frame let posterImage = animatedImage.animatedImageFrame(at: 0) XCTAssertEqual(size, posterImage?.size) expectation.fulfill() } else { XCTFail("WebImage animated image invalid") } }.onFailure { error in XCTFail(error.localizedDescription) } _ = try introspectView.inspect() ViewHosting.host(view: introspectView) self.waitForExpectations(timeout: 5, handler: nil) ViewHosting.expel() } func testWebImageModifier() throws { let expectation = self.expectation(description: "WebImage modifier") let imageUrl = URL(string: "https://raw.githubusercontent.com/ibireme/YYImage/master/Demo/YYImageDemo/mew_baseline.jpg") let imageView = WebImage(url: imageUrl, options: [.progressiveLoad], context: [.imageScaleFactor: 1]) { image in image.resizable() } placeholder: { Circle() } let introspectView = imageView .onSuccess { _, _, _ in expectation.fulfill() } .onFailure { _ in XCTFail() } .onProgress { _, _ in } // Image .resizable() .renderingMode(.original) .interpolation(.high) .antialiased(true) // Animation .runLoopMode(.common) .customLoopCount(1) .maxBufferSize(0) .pausable(true) .purgeable(true) .playbackRate(1) // WebImage .retryOnAppear(true) .cancelOnDisappear(true) .indicator(.activity) .transition(.fade) .animation(.easeInOut) _ = try introspectView.inspect() ViewHosting.host(view: introspectView) self.waitForExpectations(timeout: 5, handler: nil) ViewHosting.expel() } func testWebImageOnSuccessWhenMemoryCacheHit() throws { let expectation = self.expectation(description: "WebImage onSuccess when memory cache hit") let imageUrl = URL(string: "https://foo.bar/buzz.png") let cacheKey = SDWebImageManager.shared.cacheKey(for: imageUrl) #if os(macOS) let testImage = TestUtils.testImageBundle().image(forResource: "TestImage") #else let testImage = UIImage(named: "TestImage", in: TestUtils.testImageBundle(), compatibleWith: nil) #endif SDImageCache.shared.storeImage(toMemory: testImage, forKey: cacheKey) let imageView = WebImage(url: imageUrl) let introspectView = imageView.onSuccess { image, data, cacheType in XCTAssert(cacheType == .memory) XCTAssertNotNil(image) XCTAssertEqual(image, testImage) expectation.fulfill() } _ = try introspectView.inspect() ViewHosting.host(view: introspectView) self.waitForExpectations(timeout: 5, handler: nil) ViewHosting.expel() } func testWebImageOnSuccessWhenCacheMiss() throws { let expectation = self.expectation(description: "WebImage onSuccess when cache miss") let imageUrl = URL(string: "https://placehold.co/100x100.png") let cacheKey = SDWebImageManager.shared.cacheKey(for: imageUrl) SDImageCache.shared.removeImageFromMemory(forKey: cacheKey) SDImageCache.shared.removeImageFromDisk(forKey: cacheKey) let imageView = WebImage(url: imageUrl) let introspectView = imageView.onSuccess { image, data, cacheType in XCTAssert(cacheType == .none) XCTAssertNotNil(image) XCTAssertNotNil(data) expectation.fulfill() } _ = try introspectView.inspect() ViewHosting.host(view: introspectView) self.waitForExpectations(timeout: 5, handler: nil) ViewHosting.expel() } func testWebImageEXIFImage() throws { let expectation = self.expectation(description: "WebImage EXIF image url") // EXIF 5, Left Mirrored let imageUrl = URL(string: "https://raw.githubusercontent.com/recurser/exif-orientation-examples/master/Landscape_5.jpg") let imageView = WebImage(url: imageUrl) let introspectView = imageView.onSuccess { image, data, cacheType in #if os(macOS) let displayImage = try? imageView.inspect().zStack().image(0).actualImage().nsImage() XCTAssertNotNil(displayImage) #else let displayImage = try? imageView.inspect().zStack().image(0).actualImage().cgImage() let orientation = try? imageView.inspect().zStack().image(0).actualImage().orientation() XCTAssertNotNil(displayImage) XCTAssertEqual(orientation, .leftMirrored) #endif expectation.fulfill() }.onFailure { error in XCTFail(error.localizedDescription) } _ = try introspectView.inspect() ViewHosting.host(view: introspectView) self.waitForExpectations(timeout: 5, handler: nil) ViewHosting.expel() } }