Skip to content

Commit f193c61

Browse files
committed
Update the unit test to use the latest version of ViewInspector, which allows UIView/NSView inspection
1 parent 53de385 commit f193c61

File tree

8 files changed

+113
-164
lines changed

8 files changed

+113
-164
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,7 @@ SDWebImageSwiftUI has Unit Test to increase code quality. For SwiftUI, there are
355355

356356
However, since SwiftUI is State-Based and Attributed-Implemented layout system, there are open source projects who provide the solution:
357357

358-
+ [ViewInspector](https://github.com/nalexn/ViewInspector): Inspect View's runtime attribute value (like `.frame` modifier, `.image` value). We use this to test `AnimatedImage` and `WebImage`
359-
+ [SwiftUI-Introspect](https://github.com/siteline/SwiftUI-Introspect): Introspect the native UIKit/AppKit View, even for SwiftUI component (like `List`, which is actually `UITableView` in implementation). We use this to test `AnimatedImage`
358+
+ [ViewInspector](https://github.com/nalexn/ViewInspector): Inspect View's runtime attribute value (like `.frame` modifier, `.image` value). We use this to test `AnimatedImage` and `WebImage`. It also allows the inspect to native UIView/NSView, which we use to test `ActivityIndicator` and `ProgressIndicator`.
360359

361360
To run the test:
362361

SDWebImageSwiftUI.xcodeproj/project.pbxproj

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
321C1D5D23DEC222009CF62A /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3211F85423DE9D2700FC757F /* Images.bundle */; };
2222
321C1D5E23DEC22D009CF62A /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43E2922FD586200BE87F5 /* SDWebImage.framework */; };
2323
321C1D6023DEC231009CF62A /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = 321C1D5F23DEC231009CF62A /* ViewInspector */; };
24-
321C1D6523DEDB23009CF62A /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 321C1D6423DEDB23009CF62A /* Introspect */; };
25-
321C1D6723DEDB8E009CF62A /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 321C1D6623DEDB8E009CF62A /* Introspect */; };
26-
321C1D6923DEDB91009CF62A /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 321C1D6823DEDB91009CF62A /* Introspect */; };
2724
321C1D6A23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84623DE984D00FC757F /* AnimatedImageTests.swift */; };
2825
321C1D6B23DEDB98009CF62A /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84F23DE98E300FC757F /* WebImageTests.swift */; };
2926
321C1D6C23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84623DE984D00FC757F /* AnimatedImageTests.swift */; };
@@ -192,7 +189,6 @@
192189
buildActionMask = 2147483647;
193190
files = (
194191
321C1D3323DEA28E009CF62A /* SDWebImage.framework in Frameworks */,
195-
321C1D6523DEDB23009CF62A /* Introspect in Frameworks */,
196192
3211F84923DE984D00FC757F /* SDWebImageSwiftUI.framework in Frameworks */,
197193
3211F85323DE996700FC757F /* ViewInspector in Frameworks */,
198194
);
@@ -203,7 +199,6 @@
203199
buildActionMask = 2147483647;
204200
files = (
205201
321C1D5B23DEC219009CF62A /* SDWebImage.framework in Frameworks */,
206-
321C1D6723DEDB8E009CF62A /* Introspect in Frameworks */,
207202
321C1D4023DEC17D009CF62A /* SDWebImageSwiftUI.framework in Frameworks */,
208203
321C1D5A23DEC207009CF62A /* ViewInspector in Frameworks */,
209204
);
@@ -214,7 +209,6 @@
214209
buildActionMask = 2147483647;
215210
files = (
216211
321C1D5E23DEC22D009CF62A /* SDWebImage.framework in Frameworks */,
217-
321C1D6923DEDB91009CF62A /* Introspect in Frameworks */,
218212
321C1D4F23DEC185009CF62A /* SDWebImageSwiftUI.framework in Frameworks */,
219213
321C1D6023DEC231009CF62A /* ViewInspector in Frameworks */,
220214
);
@@ -400,7 +394,6 @@
400394
name = SDWebImageSwiftUITests;
401395
packageProductDependencies = (
402396
3211F85223DE996700FC757F /* ViewInspector */,
403-
321C1D6423DEDB23009CF62A /* Introspect */,
404397
);
405398
productName = SDWebImageSwiftUITests;
406399
productReference = 3211F84423DE984D00FC757F /* SDWebImageSwiftUITests.xctest */;
@@ -423,7 +416,6 @@
423416
name = "SDWebImageSwiftUITests macOS";
424417
packageProductDependencies = (
425418
321C1D5923DEC207009CF62A /* ViewInspector */,
426-
321C1D6623DEDB8E009CF62A /* Introspect */,
427419
);
428420
productName = "SDWebImageSwiftUITests macOS";
429421
productReference = 321C1D3B23DEC17D009CF62A /* SDWebImageSwiftUITests macOS.xctest */;
@@ -446,7 +438,6 @@
446438
name = "SDWebImageSwiftUITests tvOS";
447439
packageProductDependencies = (
448440
321C1D5F23DEC231009CF62A /* ViewInspector */,
449-
321C1D6823DEDB91009CF62A /* Introspect */,
450441
);
451442
productName = "SDWebImageSwiftUITests tvOS";
452443
productReference = 321C1D4A23DEC185009CF62A /* SDWebImageSwiftUITests tvOS.xctest */;
@@ -576,7 +567,6 @@
576567
mainGroup = 32C43DC222FD540D00BE87F5;
577568
packageReferences = (
578569
3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */,
579-
321C1D6323DEDB23009CF62A /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
580570
);
581571
productRefGroup = 32C43DCD22FD540D00BE87F5 /* Products */;
582572
projectDirPath = "";
@@ -1420,15 +1410,7 @@
14201410
repositoryURL = "https://github.com/nalexn/ViewInspector.git";
14211411
requirement = {
14221412
kind = upToNextMajorVersion;
1423-
minimumVersion = 0.0.0;
1424-
};
1425-
};
1426-
321C1D6323DEDB23009CF62A /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
1427-
isa = XCRemoteSwiftPackageReference;
1428-
repositoryURL = "https://github.com/dreampiggy/SwiftUI-Introspect.git";
1429-
requirement = {
1430-
kind = upToNextMajorVersion;
1431-
minimumVersion = 0.0.0;
1413+
minimumVersion = 0.3.5;
14321414
};
14331415
};
14341416
/* End XCRemoteSwiftPackageReference section */
@@ -1449,21 +1431,6 @@
14491431
package = 3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */;
14501432
productName = ViewInspector;
14511433
};
1452-
321C1D6423DEDB23009CF62A /* Introspect */ = {
1453-
isa = XCSwiftPackageProductDependency;
1454-
package = 321C1D6323DEDB23009CF62A /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
1455-
productName = Introspect;
1456-
};
1457-
321C1D6623DEDB8E009CF62A /* Introspect */ = {
1458-
isa = XCSwiftPackageProductDependency;
1459-
package = 321C1D6323DEDB23009CF62A /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
1460-
productName = Introspect;
1461-
};
1462-
321C1D6823DEDB91009CF62A /* Introspect */ = {
1463-
isa = XCSwiftPackageProductDependency;
1464-
package = 321C1D6323DEDB23009CF62A /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
1465-
productName = Introspect;
1466-
};
14671434
/* End XCSwiftPackageProductDependency section */
14681435
};
14691436
rootObject = 32C43DC322FD540D00BE87F5 /* Project object */;

SDWebImageSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 2 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,22 @@ public typealias PlatformViewRepresentable = UIViewRepresentable
5555
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
5656
public typealias PlatformViewRepresentable = WKInterfaceObjectRepresentable
5757
#endif
58+
59+
#if os(macOS)
60+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
61+
extension NSViewRepresentable {
62+
typealias PlatformViewType = NSViewType
63+
}
64+
#endif
65+
#if os(iOS) || os(tvOS)
66+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
67+
extension UIViewRepresentable {
68+
typealias PlatformViewType = UIViewType
69+
}
70+
#endif
71+
#if os(watchOS)
72+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
73+
extension WKInterfaceObjectRepresentable {
74+
typealias PlatformViewType = WKInterfaceObjectType
75+
}
76+
#endif

Tests/AnimatedImageTests.swift

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,10 @@
11
import XCTest
22
import SwiftUI
33
import ViewInspector
4-
import Introspect
54
@testable import SDWebImageSwiftUI
65

76
extension AnimatedImage : Inspectable {}
87

9-
extension View {
10-
func introspectAnimatedImage(customize: @escaping (SDAnimatedImageView) -> ()) -> some View {
11-
return inject(IntrospectionView(
12-
selector: { introspectionView in
13-
guard let viewHost = Introspect.findViewHost(from: introspectionView) else {
14-
return nil
15-
}
16-
return Introspect.previousSibling(containing: SDAnimatedImageView.self, from: viewHost)
17-
},
18-
customize: customize
19-
))
20-
}
21-
}
22-
238
extension AnimatedImage {
249
struct WrapperView: View & Inspectable {
2510
var name: String
@@ -51,44 +36,45 @@ class AnimatedImageTests: XCTestCase {
5136

5237
func testAnimatedImageWithName() throws {
5338
let expectation = self.expectation(description: "AnimatedImage name initializer")
54-
let imageView = AnimatedImage(name: "TestImage.gif", bundle: TestUtils.testImageBundle())
55-
let introspectView = imageView.introspectAnimatedImage { animatedImageView in
56-
if let animatedImage = animatedImageView.image as? SDAnimatedImage {
57-
XCTAssertEqual(animatedImage.animatedImageLoopCount, 0)
58-
XCTAssertEqual(animatedImage.animatedImageFrameCount, 5)
59-
} else {
60-
XCTFail("SDAnimatedImageView.image invalid")
61-
}
62-
expectation.fulfill()
39+
let imageName = "TestImage.gif"
40+
let imageView = AnimatedImage(name: imageName, bundle: TestUtils.testImageBundle())
41+
ViewHosting.host(view: imageView)
42+
let animatedImageView = try imageView.inspect().actualView().platformView().wrapped
43+
if let animatedImage = animatedImageView.image as? SDAnimatedImage {
44+
XCTAssertEqual(animatedImage.animatedImageLoopCount, 0)
45+
XCTAssertEqual(animatedImage.animatedImageFrameCount, 5)
46+
} else {
47+
XCTFail("SDAnimatedImageView.image invalid")
6348
}
64-
_ = try introspectView.inspect(AnimatedImage.self)
65-
ViewHosting.host(view: introspectView)
49+
XCTAssertEqual(animatedImageView.sd_imageName, imageName)
50+
expectation.fulfill()
6651
self.waitForExpectations(timeout: 5, handler: nil)
52+
ViewHosting.expel()
6753
}
6854

6955
func testAnimatedImageWithData() throws {
7056
let expectation = self.expectation(description: "AnimatedImage data initializer")
7157
let imageData = try XCTUnwrap(TestUtils.testImageData(name: "TestImageAnimated.apng"))
7258
let imageView = AnimatedImage(data: imageData)
73-
let introspectView = imageView.introspectAnimatedImage { animatedImageView in
74-
if let animatedImage = animatedImageView.image as? SDAnimatedImage {
75-
XCTAssertEqual(animatedImage.animatedImageLoopCount, 0)
76-
XCTAssertEqual(animatedImage.animatedImageFrameCount, 101)
77-
} else {
78-
XCTFail("SDAnimatedImageView.image invalid")
79-
}
80-
expectation.fulfill()
59+
ViewHosting.host(view: imageView)
60+
let animatedImageView = try imageView.inspect().actualView().platformView().wrapped
61+
if let animatedImage = animatedImageView.image as? SDAnimatedImage {
62+
XCTAssertEqual(animatedImage.animatedImageLoopCount, 0)
63+
XCTAssertEqual(animatedImage.animatedImageFrameCount, 101)
64+
} else {
65+
XCTFail("SDAnimatedImageView.image invalid")
8166
}
82-
_ = try introspectView.inspect(AnimatedImage.self)
83-
ViewHosting.host(view: introspectView)
67+
XCTAssertEqual(animatedImageView.sd_imageData, imageData)
68+
expectation.fulfill()
8469
self.waitForExpectations(timeout: 5, handler: nil)
70+
ViewHosting.expel()
8571
}
8672

8773
func testAnimatedImageWithURL() throws {
8874
let expectation = self.expectation(description: "AnimatedImage url initializer")
8975
let imageUrl = URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif")
9076
let imageView = AnimatedImage(url: imageUrl)
91-
let introspectView = imageView.onSuccess { image, cacheType in
77+
.onSuccess { image, cacheType in
9278
if let animatedImage = image as? SDAnimatedImage {
9379
XCTAssertEqual(animatedImage.animatedImageLoopCount, 0)
9480
XCTAssertEqual(animatedImage.animatedImageFrameCount, 389)
@@ -99,9 +85,11 @@ class AnimatedImageTests: XCTestCase {
9985
}.onFailure { error in
10086
XCTFail(error.localizedDescription)
10187
}
102-
_ = try introspectView.inspect(AnimatedImage.self)
103-
ViewHosting.host(view: introspectView)
88+
ViewHosting.host(view: imageView)
89+
let animatedImageView = try imageView.inspect().actualView().platformView().wrapped
90+
XCTAssertEqual(animatedImageView.sd_imageURL, imageUrl)
10491
self.waitForExpectations(timeout: 5, handler: nil)
92+
ViewHosting.expel()
10593
}
10694

10795
func testAnimatedImageBinding() throws {
@@ -151,15 +139,12 @@ class AnimatedImageTests: XCTestCase {
151139
}
152140
ViewHosting.host(view: wrapperView)
153141
self.waitForExpectations(timeout: 5, handler: nil)
142+
ViewHosting.expel()
154143
}
155144

156145
func testAnimatedImageModifier() throws {
157146
let expectation = self.expectation(description: "WebImage modifier")
158147
let imageUrl = URL(string: "https://assets.sbnation.com/assets/2512203/dogflops.gif")
159-
AnimatedImage.onViewDestroy { view, coordinator in
160-
XCTAssert(view.isKind(of: SDAnimatedImageView.self))
161-
XCTAssertEqual(coordinator.userInfo?["foo"] as? String, "bar")
162-
}
163148
let imageView = AnimatedImage(url: imageUrl, options: [.progressiveLoad], context: [.imageScaleFactor: 1])
164149
let introspectView = imageView
165150
.onSuccess { _, _ in
@@ -195,9 +180,9 @@ class AnimatedImageTests: XCTestCase {
195180
.playbackRate(1)
196181
.transition(.fade)
197182
.animation(.easeInOut)
198-
_ = try introspectView.inspect(AnimatedImage.self)
183+
_ = try introspectView.inspect()
199184
ViewHosting.host(view: introspectView)
200185
self.waitForExpectations(timeout: 5, handler: nil)
201-
AnimatedImage.onViewDestroy()
186+
ViewHosting.expel()
202187
}
203188
}

0 commit comments

Comments
 (0)