ApiServiceTests.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. // Copyright 2023 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import FirebaseCore
  15. import XCTest
  16. @testable import FirebaseAppDistributionInternal
  17. @testable import FirebaseInstallations
  18. class ApiServiceTests: XCTestCase {
  19. override class func setUp() {
  20. let options = FirebaseOptions(
  21. googleAppID: "0:0000000000000:ios:0000000000000000",
  22. gcmSenderID: "00000000000000000-00000000000-000000000"
  23. )
  24. options.projectID = "myProjectID"
  25. // Randomly generated, this needs to start with A, and be 39 characters long.
  26. options.apiKey = "A7a8Ff2UsWT3r5lOg22fFFkVwZClxc2MsvfPPFS"
  27. FirebaseApp.configure(name: "app-distribution-test-app", options: options)
  28. _ = FirebaseApp.app(name: "app-distribution-test-app")
  29. }
  30. // MARK: - Test generateAuthToken
  31. func testGenerateAuthTokenSuccess() {
  32. let installations = FakeInstallations(testCase: .success)
  33. let expectation = XCTestExpectation(description: "Generate auth token succeeds")
  34. ApiService.generateAuthToken(
  35. installations: installations,
  36. completion: { identifier, authTokenResult, error in
  37. XCTAssertNotNil(identifier)
  38. XCTAssertNotNil(authTokenResult)
  39. XCTAssertNil(error)
  40. expectation.fulfill()
  41. }
  42. )
  43. wait(for: [expectation], timeout: 5)
  44. }
  45. func testGenerateAuthTokenAuthTokenFailure() {
  46. let installations = FakeInstallations(testCase: .authTokenFailure)
  47. let expectation =
  48. XCTestExpectation(description: "Generate auth token fails to generate auth token.")
  49. ApiService.generateAuthToken(
  50. installations: installations,
  51. completion: { identifier, authTokenResult, error in
  52. let nserror = error as? NSError
  53. XCTAssertNil(identifier)
  54. XCTAssertNil(authTokenResult)
  55. XCTAssertNotNil(error)
  56. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiTokenGenerationFailure.rawValue)
  57. expectation.fulfill()
  58. }
  59. )
  60. wait(for: [expectation], timeout: 5)
  61. }
  62. func testGenerateAuthTokenInstallationIDFailure() {
  63. let installations = FakeInstallations(testCase: .installationIDFailure)
  64. let expectation = XCTestExpectation(description: "Generate auth token fails to find ID.")
  65. ApiService.generateAuthToken(
  66. installations: installations,
  67. completion: { identifier, authTokenResult, error in
  68. let nserror = error as? NSError
  69. XCTAssertNil(identifier)
  70. XCTAssertNil(authTokenResult)
  71. XCTAssertNotNil(error)
  72. XCTAssertEqual(
  73. nserror?.code,
  74. AppDistributionApiError.ApiInstallationIdentifierError.rawValue
  75. )
  76. expectation.fulfill()
  77. }
  78. )
  79. wait(for: [expectation], timeout: 5)
  80. }
  81. // MARK: - Test fetchReleases
  82. func testFetchReleasesSuccess() {
  83. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  84. let installations = FakeInstallations(testCase: .success)
  85. let expectedReleases: [[String: AnyHashable]] = [
  86. [
  87. "displayVersion": "1.0.0",
  88. "buildVersion": "111",
  89. "releaseNotes": "This is a release",
  90. "downloadURL": "http://faketyfakefake.download",
  91. ],
  92. [
  93. "latest": true,
  94. "displayVersion": "1.0.1",
  95. "buildVersion": "112",
  96. "releaseNotes": "This is a release too",
  97. "downloadURL": "http://faketyfakefake.download",
  98. ],
  99. ]
  100. let response = ["releases": expectedReleases]
  101. let urlSession = URLSessionMock(
  102. testCase: .success,
  103. responseData: try! JSONSerialization.data(withJSONObject: response)
  104. )
  105. let expectation = XCTestExpectation(description: "Fetch releases succeeds with two releases.")
  106. ApiService.fetchReleases(
  107. app: app,
  108. installations: installations,
  109. urlSession: urlSession,
  110. completion: { releases, error in
  111. XCTAssertNotNil(releases)
  112. XCTAssertNil(error)
  113. XCTAssertEqual(releases?.count, 2)
  114. XCTAssertEqual(releases as? [[String: AnyHashable]?], expectedReleases)
  115. expectation.fulfill()
  116. }
  117. )
  118. wait(for: [expectation], timeout: 5)
  119. }
  120. func testFetchReleasesWithEmptyArraySuccess() {
  121. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  122. let installations = FakeInstallations(testCase: .success)
  123. let urlSession = URLSessionMock(
  124. testCase: .success,
  125. responseData: try! JSONSerialization.data(withJSONObject: ["releases": []])
  126. )
  127. let expectation = XCTestExpectation(description: "Fetch releases succeeds with 0 releases.")
  128. ApiService.fetchReleases(
  129. app: app,
  130. installations: installations,
  131. urlSession: urlSession,
  132. completion: { releases, error in
  133. XCTAssertNotNil(releases)
  134. XCTAssertNil(error)
  135. XCTAssertEqual(releases?.count, 0)
  136. XCTAssertEqual(releases as? [[String: AnyHashable]?], [])
  137. expectation.fulfill()
  138. }
  139. )
  140. wait(for: [expectation], timeout: 5)
  141. }
  142. func testFetchReleasesWithInvalidJsonFailure() {
  143. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  144. let installations = FakeInstallations(testCase: .success)
  145. let urlSession = URLSessionMock(
  146. testCase: .success,
  147. responseData: "invalid-string".data(using: .utf8)
  148. )
  149. let expectation = XCTestExpectation(description: "Fetch releases fails")
  150. ApiService.fetchReleases(
  151. app: app,
  152. installations: installations,
  153. urlSession: urlSession,
  154. completion: { releases, error in
  155. let nserror = error as? NSError
  156. XCTAssertNil(releases)
  157. XCTAssertNotNil(nserror)
  158. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorParseFailure.rawValue)
  159. expectation.fulfill()
  160. }
  161. )
  162. wait(for: [expectation], timeout: 5)
  163. }
  164. func testFetchReleasesUnknownFailure() {
  165. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  166. let installations = FakeInstallations(testCase: .success)
  167. let urlSession = URLSessionMock(testCase: .unknownFailure)
  168. let expectation = XCTestExpectation(description: "Fetch releases fails with unknown error.")
  169. ApiService.fetchReleases(
  170. app: app,
  171. installations: installations,
  172. urlSession: urlSession,
  173. completion: { releases, error in
  174. let nserror = error as? NSError
  175. XCTAssertNil(releases)
  176. XCTAssertNotNil(nserror)
  177. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnknownFailure.rawValue)
  178. expectation.fulfill()
  179. }
  180. )
  181. wait(for: [expectation], timeout: 5)
  182. }
  183. func testFetchReleasesUnauthenticatedFailure() {
  184. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  185. let installations = FakeInstallations(testCase: .success)
  186. let urlSession = URLSessionMock(testCase: .unauthenticatedFailure)
  187. let expectation =
  188. XCTestExpectation(description: "Fetch releases fails with unauthenticated error.")
  189. ApiService.fetchReleases(
  190. app: app,
  191. installations: installations,
  192. urlSession: urlSession,
  193. completion: { releases, error in
  194. let nserror = error as? NSError
  195. XCTAssertNil(releases)
  196. XCTAssertNotNil(nserror)
  197. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnauthenticated.rawValue)
  198. expectation.fulfill()
  199. }
  200. )
  201. wait(for: [expectation], timeout: 5)
  202. }
  203. // TODO: Add more cases for testFetchReleases
  204. func testFindReleaseSuccess() {
  205. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  206. let installations = FakeInstallations(testCase: .success)
  207. let urlSession = URLSessionMock(
  208. testCase: .success,
  209. responseData: try! JSONSerialization.data(withJSONObject: ["release": "release/name"])
  210. )
  211. let expectation = XCTestExpectation(description: "Find release succeeds")
  212. ApiService.findRelease(
  213. app: app,
  214. installations: installations,
  215. urlSession: urlSession,
  216. displayVersion: "display-version",
  217. buildVersion: "build-version",
  218. codeHash: "codeHash",
  219. completion: { releaseName, error in
  220. XCTAssertEqual(releaseName, "release/name")
  221. XCTAssertNil(error)
  222. expectation.fulfill()
  223. }
  224. )
  225. }
  226. func testFindReleaseWithInvalidJsonFailure() {
  227. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  228. let installations = FakeInstallations(testCase: .success)
  229. let urlSession = URLSessionMock(
  230. testCase: .success,
  231. responseData: "invalid-json".data(using: .utf8)
  232. )
  233. let expectation = XCTestExpectation(description: "Find release fails")
  234. ApiService.findRelease(
  235. app: app,
  236. installations: installations,
  237. urlSession: urlSession,
  238. displayVersion: "display-version",
  239. buildVersion: "build-version",
  240. codeHash: "codeHash",
  241. completion: { releaseName, error in
  242. XCTAssertNil(releaseName)
  243. let nserror = error as? NSError
  244. XCTAssertNotNil(nserror)
  245. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorParseFailure.rawValue)
  246. expectation.fulfill()
  247. }
  248. )
  249. }
  250. func testFindReleaseUnauthenticatedFailure() {
  251. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  252. let installations = FakeInstallations(testCase: .success)
  253. let urlSession = URLSessionMock(testCase: .unauthenticatedFailure)
  254. let expectation = XCTestExpectation(description: "Find release fails")
  255. ApiService.findRelease(
  256. app: app,
  257. installations: installations,
  258. urlSession: urlSession,
  259. displayVersion: "display-version",
  260. buildVersion: "build-version",
  261. codeHash: "codeHash",
  262. completion: { releaseName, error in
  263. XCTAssertNil(releaseName)
  264. let nserror = error as? NSError
  265. XCTAssertNotNil(nserror)
  266. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnauthenticated.rawValue)
  267. expectation.fulfill()
  268. }
  269. )
  270. }
  271. func testFindReleaseUnknownFailure() {
  272. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  273. let installations = FakeInstallations(testCase: .success)
  274. let urlSession = URLSessionMock(testCase: .unknownFailure)
  275. let expectation = XCTestExpectation(description: "Find release fails")
  276. ApiService.findRelease(
  277. app: app,
  278. installations: installations,
  279. urlSession: urlSession,
  280. displayVersion: "display-version",
  281. buildVersion: "build-version",
  282. codeHash: "codeHash",
  283. completion: { releaseName, error in
  284. XCTAssertNil(releaseName)
  285. let nserror = error as? NSError
  286. XCTAssertNotNil(nserror)
  287. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnknownFailure.rawValue)
  288. expectation.fulfill()
  289. }
  290. )
  291. }
  292. func testCreateFeedbackSuccess() {
  293. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  294. let installations = FakeInstallations(testCase: .success)
  295. let urlSession = URLSessionMock(
  296. testCase: .success,
  297. responseData: try! JSONSerialization.data(withJSONObject: ["name": "feedback/name"])
  298. )
  299. let expectation = XCTestExpectation(description: "Create feedback succeeds")
  300. ApiService.createFeedback(
  301. app: app,
  302. installations: installations,
  303. urlSession: urlSession,
  304. releaseName: "release/name",
  305. feedbackText: "feedback text",
  306. completion: { feedbackName, error in
  307. XCTAssertEqual(feedbackName, "feedback/name")
  308. XCTAssertNil(error)
  309. expectation.fulfill()
  310. }
  311. )
  312. wait(for: [expectation], timeout: 5)
  313. }
  314. func testCreateFeedbackWithInvalidJsonFailure() {
  315. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  316. let installations = FakeInstallations(testCase: .success)
  317. let urlSession = URLSessionMock(
  318. testCase: .success,
  319. responseData: "invalid-json".data(using: .utf8)
  320. )
  321. let expectation = XCTestExpectation(description: "Create feedback fails")
  322. ApiService.createFeedback(
  323. app: app,
  324. installations: installations,
  325. urlSession: urlSession,
  326. releaseName: "release/name",
  327. feedbackText: "feedback text",
  328. completion: { feedbackName, error in
  329. XCTAssertNil(feedbackName)
  330. let nserror = error as? NSError
  331. XCTAssertNotNil(nserror)
  332. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorParseFailure.rawValue)
  333. expectation.fulfill()
  334. }
  335. )
  336. }
  337. func testCreateFeedbackUnauthenticatedFailure() {
  338. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  339. let installations = FakeInstallations(testCase: .success)
  340. let urlSession = URLSessionMock(testCase: .unauthenticatedFailure)
  341. let expectation = XCTestExpectation(description: "Create feedback fails")
  342. ApiService.createFeedback(
  343. app: app,
  344. installations: installations,
  345. urlSession: urlSession,
  346. releaseName: "release/name",
  347. feedbackText: "feedback text",
  348. completion: { feedbackName, error in
  349. XCTAssertNil(feedbackName)
  350. let nserror = error as? NSError
  351. XCTAssertNotNil(nserror)
  352. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnauthenticated.rawValue)
  353. expectation.fulfill()
  354. }
  355. )
  356. wait(for: [expectation], timeout: 5)
  357. }
  358. func testCreateFeedbackWithCompletionUnknownFailure() {
  359. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  360. let installations = FakeInstallations(testCase: .success)
  361. let urlSession = URLSessionMock(testCase: .unknownFailure)
  362. let expectation = XCTestExpectation(description: "Create feedback fails")
  363. ApiService.createFeedback(
  364. app: app,
  365. installations: installations,
  366. urlSession: urlSession,
  367. releaseName: "release/name",
  368. feedbackText: "feedback text",
  369. completion: { feedbackName, error in
  370. XCTAssertNil(feedbackName)
  371. let nserror = error as? NSError
  372. XCTAssertNotNil(nserror)
  373. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnknownFailure.rawValue)
  374. expectation.fulfill()
  375. }
  376. )
  377. wait(for: [expectation], timeout: 5)
  378. }
  379. func testUploadImageSuccess() {
  380. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  381. let installations = FakeInstallations(testCase: .success)
  382. let urlSession = URLSessionMock(testCase: .success)
  383. let expectation = XCTestExpectation(description: "Upload image succeeds")
  384. ApiService.uploadImage(
  385. app: app,
  386. installations: installations,
  387. urlSession: urlSession,
  388. feedbackName: "feedback/name",
  389. image: UIImage(),
  390. completion: { error in
  391. XCTAssertNil(error)
  392. expectation.fulfill()
  393. }
  394. )
  395. wait(for: [expectation], timeout: 5)
  396. }
  397. func testUploadImageUnauthenticatedFailure() {
  398. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  399. let installations = FakeInstallations(testCase: .success)
  400. let urlSession = URLSessionMock(testCase: .unauthenticatedFailure)
  401. let expectation = XCTestExpectation(description: "Upload image fails")
  402. ApiService.uploadImage(
  403. app: app,
  404. installations: installations,
  405. urlSession: urlSession,
  406. feedbackName: "feedback/name",
  407. image: UIImage(),
  408. completion: { error in
  409. let nserror = error as? NSError
  410. XCTAssertNotNil(nserror)
  411. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnauthenticated.rawValue)
  412. expectation.fulfill()
  413. }
  414. )
  415. wait(for: [expectation], timeout: 5)
  416. }
  417. func testUploadImageWithCompletionUnknownFailure() {
  418. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  419. let installations = FakeInstallations(testCase: .success)
  420. let urlSession = URLSessionMock(testCase: .unknownFailure)
  421. let expectation = XCTestExpectation(description: "Upload image fails")
  422. ApiService.uploadImage(
  423. app: app,
  424. installations: installations,
  425. urlSession: urlSession,
  426. feedbackName: "feedback/name",
  427. image: UIImage(),
  428. completion: { error in
  429. let nserror = error as? NSError
  430. XCTAssertNotNil(nserror)
  431. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnknownFailure.rawValue)
  432. expectation.fulfill()
  433. }
  434. )
  435. wait(for: [expectation], timeout: 5)
  436. }
  437. func testCommitFeedbackSuccess() {
  438. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  439. let installations = FakeInstallations(testCase: .success)
  440. let urlSession = URLSessionMock(
  441. testCase: .success,
  442. responseData: try! JSONSerialization.data(withJSONObject: ["name": "feedback/name"])
  443. )
  444. let expectation = XCTestExpectation(description: "Commit feedback succeeds")
  445. ApiService.commitFeedback(
  446. app: app,
  447. installations: installations,
  448. urlSession: urlSession,
  449. feedbackName: "feedback/name",
  450. completion: { error in
  451. XCTAssertNil(error)
  452. expectation.fulfill()
  453. }
  454. )
  455. wait(for: [expectation], timeout: 5)
  456. }
  457. func testCommitFeedbackUnauthenticatedFailure() {
  458. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  459. let installations = FakeInstallations(testCase: .success)
  460. let urlSession = URLSessionMock(testCase: .unauthenticatedFailure)
  461. let expectation = XCTestExpectation(description: "Commit feedback fails")
  462. ApiService.commitFeedback(
  463. app: app,
  464. installations: installations,
  465. urlSession: urlSession,
  466. feedbackName: "feedback/name",
  467. completion: { error in
  468. let nserror = error as? NSError
  469. XCTAssertNotNil(nserror)
  470. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnauthenticated.rawValue)
  471. expectation.fulfill()
  472. }
  473. )
  474. wait(for: [expectation], timeout: 5)
  475. }
  476. func testCommitFeedbackWithCompletionUnknownFailure() {
  477. let app = FirebaseApp.app(name: "app-distribution-test-app")!
  478. let installations = FakeInstallations(testCase: .success)
  479. let urlSession = URLSessionMock(testCase: .unknownFailure)
  480. let expectation = XCTestExpectation(description: "Commit feedback fails")
  481. ApiService.commitFeedback(
  482. app: app,
  483. installations: installations,
  484. urlSession: urlSession,
  485. feedbackName: "feedback/name",
  486. completion: { error in
  487. let nserror = error as? NSError
  488. XCTAssertNotNil(nserror)
  489. XCTAssertEqual(nserror?.code, AppDistributionApiError.ApiErrorUnknownFailure.rawValue)
  490. expectation.fulfill()
  491. }
  492. )
  493. wait(for: [expectation], timeout: 5)
  494. }
  495. }