UIImageViewExtensionTests.swift 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. //
  2. // UIImageViewExtensionTests.swift
  3. // Kingfisher
  4. //
  5. // Created by Wei Wang on 15/4/17.
  6. //
  7. // Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. import UIKit
  27. import XCTest
  28. @testable import Kingfisher
  29. class UIImageViewExtensionTests: XCTestCase {
  30. var imageView: UIImageView!
  31. override class func setUp() {
  32. super.setUp()
  33. LSNocilla.sharedInstance().start()
  34. }
  35. override class func tearDown() {
  36. super.tearDown()
  37. LSNocilla.sharedInstance().stop()
  38. }
  39. override func setUp() {
  40. super.setUp()
  41. // Put setup code here. This method is called before the invocation of each test method in the class.
  42. imageView = UIImageView()
  43. KingfisherManager.sharedManager.downloader = ImageDownloader(name: "testDownloader")
  44. cleanDefaultCache()
  45. }
  46. override func tearDown() {
  47. // Put teardown code here. This method is called after the invocation of each test method in the class.
  48. LSNocilla.sharedInstance().clearStubs()
  49. imageView = nil
  50. cleanDefaultCache()
  51. super.tearDown()
  52. }
  53. func testImageDownloadForImageView() {
  54. let expectation = expectationWithDescription("wait for downloading image")
  55. let URLString = testKeys[0]
  56. stubRequest("GET", URLString).andReturn(200).withBody(testImageData)
  57. let URL = NSURL(string: URLString)!
  58. var progressBlockIsCalled = false
  59. imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  60. progressBlockIsCalled = true
  61. }) { (image, error, cacheType, imageURL) -> () in
  62. expectation.fulfill()
  63. XCTAssert(progressBlockIsCalled, "progressBlock should be called at least once.")
  64. XCTAssert(image != nil, "Downloaded image should exist.")
  65. XCTAssert(image! == testImage, "Downloaded image should be the same as test image.")
  66. XCTAssert(self.imageView.image! == testImage, "Downloaded image should be already set to the image property.")
  67. XCTAssert(self.imageView.kf_webURL == imageURL, "Web URL should equal to the downloaded url.")
  68. XCTAssert(cacheType == .None, "The cache type should be none here. This image was just downloaded.")
  69. }
  70. waitForExpectationsWithTimeout(5, handler: nil)
  71. }
  72. func testImageDownloadWithResourceForImageView() {
  73. let expectation = expectationWithDescription("wait for downloading image")
  74. let URLString = testKeys[0]
  75. stubRequest("GET", URLString).andReturn(200).withBody(testImageData)
  76. let URL = NSURL(string: URLString)!
  77. let resource = Resource(downloadURL: URL)
  78. var progressBlockIsCalled = false
  79. cleanDefaultCache()
  80. imageView.kf_setImageWithResource(resource, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  81. progressBlockIsCalled = true
  82. }) { (image, error, cacheType, imageURL) -> () in
  83. expectation.fulfill()
  84. XCTAssert(progressBlockIsCalled, "progressBlock should be called at least once.")
  85. XCTAssert(image != nil, "Downloaded image should exist.")
  86. XCTAssert(image! == testImage, "Downloaded image should be the same as test image.")
  87. XCTAssert(self.imageView.image! == testImage, "Downloaded image should be already set to the image property.")
  88. XCTAssert(self.imageView.kf_webURL == imageURL, "Web URL should equal to the downloaded url.")
  89. XCTAssert(cacheType == .None, "The cache type should be none here. This image was just downloaded. But now is: \(cacheType)")
  90. }
  91. waitForExpectationsWithTimeout(5, handler: nil)
  92. }
  93. func testImageDownloadCancelForImageView() {
  94. let expectation = expectationWithDescription("wait for downloading image")
  95. let URLString = testKeys[0]
  96. stubRequest("GET", URLString).andReturn(200).withBody(testImageData)
  97. let URL = NSURL(string: URLString)!
  98. var progressBlockIsCalled = false
  99. var completionBlockIsCalled = false
  100. let task = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  101. progressBlockIsCalled = true
  102. }) { (image, error, cacheType, imageURL) -> () in
  103. completionBlockIsCalled = true
  104. }
  105. task.cancel()
  106. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.09)), dispatch_get_main_queue()) { () -> Void in
  107. expectation.fulfill()
  108. XCTAssert(progressBlockIsCalled == false, "ProgressBlock should not be called since it is canceled.")
  109. XCTAssert(completionBlockIsCalled == false, "CompletionBlock should not be called since it is canceled.")
  110. }
  111. waitForExpectationsWithTimeout(5, handler: nil)
  112. }
  113. func testImageDownloadCancelForImageViewAfterRequestStarted() {
  114. let expectation = expectationWithDescription("wait for downloading image")
  115. let URLString = testKeys[0]
  116. let stub = stubRequest("GET", URLString).andReturn(200).withBody(testImageData).delay()
  117. let URL = NSURL(string: URLString)!
  118. var progressBlockIsCalled = false
  119. var completionBlockIsCalled = false
  120. let task = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  121. progressBlockIsCalled = true
  122. }) { (image, error, cacheType, imageURL) -> () in
  123. XCTAssertNotNil(error)
  124. XCTAssertEqual(error?.code, NSURLErrorCancelled)
  125. completionBlockIsCalled = true
  126. }
  127. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.1)), dispatch_get_main_queue()) { () -> Void in
  128. task.cancel()
  129. stub.go()
  130. }
  131. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.2)), dispatch_get_main_queue()) { () -> Void in
  132. expectation.fulfill()
  133. XCTAssert(progressBlockIsCalled == false, "ProgressBlock should not be called since it is canceled.")
  134. XCTAssert(completionBlockIsCalled == true, "CompletionBlock should not be called since it is canceled.")
  135. }
  136. waitForExpectationsWithTimeout(5, handler: nil)
  137. }
  138. func testImageDownloadCancelPartialTaskBeforeRequest() {
  139. let expectation = expectationWithDescription("wait for downloading image")
  140. let URLString = testKeys[0]
  141. stubRequest("GET", URLString).andReturn(200).withBody(testImageData)
  142. let URL = NSURL(string: URLString)!
  143. var task1Completion = false
  144. var task2Completion = false
  145. var task3Completion = false
  146. let task1 = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  147. }) { (image, error, cacheType, imageURL) -> () in
  148. task1Completion = true
  149. }
  150. let _ = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  151. }) { (image, error, cacheType, imageURL) -> () in
  152. XCTAssertNotNil(image)
  153. task2Completion = true
  154. }
  155. let _ = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  156. }) { (image, error, cacheType, imageURL) -> () in
  157. XCTAssertNotNil(image)
  158. task3Completion = true
  159. }
  160. task1.cancel()
  161. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.2)), dispatch_get_main_queue()) { () -> Void in
  162. expectation.fulfill()
  163. XCTAssert(task1Completion == false, "Task 1 should be not completed since it is cancelled before downloading started.")
  164. XCTAssert(task2Completion == true, "Task 2 should be completed.")
  165. XCTAssert(task3Completion == true, "Task 3 should be completed.")
  166. }
  167. waitForExpectationsWithTimeout(5, handler: nil)
  168. }
  169. func testImageDownloadCancelPartialTaskAfterRequestStarted() {
  170. let expectation = expectationWithDescription("wait for downloading image")
  171. let URLString = testKeys[0]
  172. let stub = stubRequest("GET", URLString).andReturn(200).withBody(testImageData).delay()
  173. let URL = NSURL(string: URLString)!
  174. var task1Completion = false
  175. var task2Completion = false
  176. var task3Completion = false
  177. let task1 = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  178. }) { (image, error, cacheType, imageURL) -> () in
  179. XCTAssertNotNil(image)
  180. task1Completion = true
  181. }
  182. let _ = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  183. }) { (image, error, cacheType, imageURL) -> () in
  184. XCTAssertNotNil(image)
  185. task2Completion = true
  186. }
  187. let _ = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  188. }) { (image, error, cacheType, imageURL) -> () in
  189. XCTAssertNotNil(image)
  190. task3Completion = true
  191. }
  192. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.1)), dispatch_get_main_queue()) { () -> Void in
  193. task1.cancel()
  194. stub.go()
  195. }
  196. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.2)), dispatch_get_main_queue()) { () -> Void in
  197. expectation.fulfill()
  198. XCTAssert(task1Completion == true, "Task 1 should be completed since task 2 and 3 are not cancelled and they are sharing the same downloading process.")
  199. XCTAssert(task2Completion == true, "Task 2 should be completed.")
  200. XCTAssert(task3Completion == true, "Task 3 should be completed.")
  201. }
  202. waitForExpectationsWithTimeout(5, handler: nil)
  203. }
  204. func testImageDownloadCancelAllTasksAfterRequestStarted() {
  205. let expectation = expectationWithDescription("wait for downloading image")
  206. let URLString = testKeys[0]
  207. let stub = stubRequest("GET", URLString).andReturn(200).withBody(testImageData).delay()
  208. let URL = NSURL(string: URLString)!
  209. var task1Completion = false
  210. var task2Completion = false
  211. var task3Completion = false
  212. let task1 = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  213. }) { (image, error, cacheType, imageURL) -> () in
  214. XCTAssertNotNil(error)
  215. XCTAssertEqual(error?.code, NSURLErrorCancelled)
  216. task1Completion = true
  217. }
  218. let task2 = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  219. }) { (image, error, cacheType, imageURL) -> () in
  220. XCTAssertNotNil(error)
  221. XCTAssertEqual(error?.code, NSURLErrorCancelled)
  222. task2Completion = true
  223. }
  224. let task3 = imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  225. }) { (image, error, cacheType, imageURL) -> () in
  226. XCTAssertNotNil(error)
  227. XCTAssertEqual(error?.code, NSURLErrorCancelled)
  228. task3Completion = true
  229. }
  230. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.1)), dispatch_get_main_queue()) { () -> Void in
  231. task1.cancel()
  232. task2.cancel()
  233. task3.cancel()
  234. stub.go()
  235. }
  236. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.2)), dispatch_get_main_queue()) { () -> Void in
  237. expectation.fulfill()
  238. XCTAssert(task1Completion == true, "Task 1 should be completed with error.")
  239. XCTAssert(task2Completion == true, "Task 2 should be completed with error.")
  240. XCTAssert(task3Completion == true, "Task 3 should be completed with error.")
  241. }
  242. waitForExpectationsWithTimeout(5, handler: nil)
  243. }
  244. func testImageDownalodMultipleCaches() {
  245. let cache1 = ImageCache(name: "cache1")
  246. let cache2 = ImageCache(name: "cache2")
  247. cache1.clearDiskCache(true)
  248. cache2.clearDiskCache(true)
  249. let expectation = expectationWithDescription("wait for downloading image")
  250. let URLString = testKeys[0]
  251. stubRequest("GET", URLString).andReturn(200).withBody(testImageData)
  252. let URL = NSURL(string: URLString)!
  253. imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: [.TargetCache(cache1)], progressBlock: { (receivedSize, totalSize) -> () in
  254. }) { (image, error, cacheType, imageURL) -> () in
  255. XCTAssertTrue(cache1.isImageCachedForKey(URLString).cached, "This image should be cached in cache1.")
  256. XCTAssertFalse(cache2.isImageCachedForKey(URLString).cached, "This image should not be cached in cache2.")
  257. XCTAssertFalse(KingfisherManager.sharedManager.cache.isImageCachedForKey(URLString).cached, "This image should not be cached in default cache.")
  258. self.imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: [.TargetCache(cache2)], progressBlock: { (receivedSize, totalSize) -> () in
  259. }, completionHandler: { (image, error, cacheType, imageURL) -> () in
  260. XCTAssertTrue(cache1.isImageCachedForKey(URLString).cached, "This image should be cached in cache1.")
  261. XCTAssertTrue(cache2.isImageCachedForKey(URLString).cached, "This image should be cached in cache2.")
  262. XCTAssertFalse(KingfisherManager.sharedManager.cache.isImageCachedForKey(URLString).cached, "This image should not be cached in default cache.")
  263. clearCaches([cache1, cache2])
  264. expectation.fulfill()
  265. })
  266. }
  267. waitForExpectationsWithTimeout(5, handler: { (error) -> Void in
  268. clearCaches([cache1, cache2])
  269. })
  270. }
  271. func testIndicatorViewExisting() {
  272. imageView.kf_showIndicatorWhenLoading = true
  273. XCTAssertNotNil(imageView.kf_indicator, "The indicator view should exist when showIndicatorWhenLoading is true")
  274. imageView.kf_showIndicatorWhenLoading = false
  275. XCTAssertNil(imageView.kf_indicator, "The indicator view should be removed when showIndicatorWhenLoading set to false")
  276. }
  277. func testIndicatorViewAnimating() {
  278. imageView.kf_showIndicatorWhenLoading = true
  279. let expectation = expectationWithDescription("wait for downloading image")
  280. let URLString = testKeys[0]
  281. stubRequest("GET", URLString).andReturn(200).withBody(testImageData)
  282. let URL = NSURL(string: URLString)!
  283. imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  284. let indicator = self.imageView.kf_indicator
  285. XCTAssertNotNil(indicator, "The indicator view should exist when showIndicatorWhenLoading is true")
  286. XCTAssertTrue(indicator!.isAnimating(), "The indicator should be animating when loading")
  287. }) { (image, error, cacheType, imageURL) -> () in
  288. let indicator = self.imageView.kf_indicator
  289. XCTAssertFalse(indicator!.isAnimating(), "The indicator should stop after loading")
  290. expectation.fulfill()
  291. }
  292. waitForExpectationsWithTimeout(5, handler: nil)
  293. }
  294. func testCacnelImageTask() {
  295. let expectation = expectationWithDescription("wait for downloading image")
  296. let URLString = testKeys[0]
  297. let stub = stubRequest("GET", URLString).andReturn(200).withBody(testImageData).delay()
  298. let URL = NSURL(string: URLString)!
  299. imageView.kf_setImageWithURL(URL, placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  300. XCTFail("Progress block should not be called.")
  301. }) { (image, error, cacheType, imageURL) -> () in
  302. XCTAssertNotNil(error)
  303. XCTAssertEqual(error?.code, NSURLErrorCancelled)
  304. expectation.fulfill()
  305. }
  306. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.1)), dispatch_get_main_queue()) { () -> Void in
  307. self.imageView.kf_cancelDownloadTask()
  308. stub.go()
  309. }
  310. waitForExpectationsWithTimeout(5, handler: nil)
  311. }
  312. func testDownloadForMutipleURLs() {
  313. let expectation = expectationWithDescription("wait for downloading image")
  314. let URLStrings = [testKeys[0], testKeys[1]]
  315. stubRequest("GET", URLStrings[0]).andReturn(200).withBody(testImageData)
  316. stubRequest("GET", URLStrings[1]).andReturn(200).withBody(testImageData)
  317. let URLs = URLStrings.map{NSURL(string: $0)!}
  318. var task1Complete = false
  319. var task2Complete = false
  320. imageView.kf_setImageWithURL(URLs[0], placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  321. }) { (image, error, cacheType, imageURL) -> () in
  322. task1Complete = true
  323. XCTAssertNotNil(image)
  324. XCTAssertEqual(imageURL, URLs[0])
  325. XCTAssertNotEqual(self.imageView.image, image)
  326. }
  327. self.imageView.kf_setImageWithURL(URLs[1], placeholderImage: nil, optionsInfo: nil, progressBlock: { (receivedSize, totalSize) -> () in
  328. }) { (image, error, cacheType, imageURL) -> () in
  329. task2Complete = true
  330. XCTAssertNotNil(image)
  331. XCTAssertEqual(imageURL, URLs[1])
  332. XCTAssertEqual(self.imageView.image, image)
  333. }
  334. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * 0.1)), dispatch_get_main_queue()) { () -> Void in
  335. XCTAssertTrue(task1Complete, "Task 1 should be completed.")
  336. XCTAssertTrue(task2Complete, "Task 2 should be completed.")
  337. expectation.fulfill()
  338. }
  339. waitForExpectationsWithTimeout(5, handler: nil)
  340. }
  341. }