| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474 |
- //
- // CombineTests.swift
- //
- // Copyright (c) 2020 Alamofire Software Foundation (http://alamofire.org/)
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #if canImport(Combine)
- import Alamofire
- import Combine
- import XCTest
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- final class DataRequestCombineTests: CombineTestCase {
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanBePublished() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DataResponse<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatNonAutomaticDataRequestCanBePublished() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let session = Session(startRequestsImmediately: false)
- var response: DataResponse<TestResponse, AFError>?
- // When
- store {
- session.request(.default)
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanPublishData() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let session = Session(startRequestsImmediately: false)
- var response: DataResponse<Data, AFError>?
- // When
- store {
- session.request(.default)
- .publishData()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanPublishString() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let session = Session(startRequestsImmediately: false)
- var response: DataResponse<String, AFError>?
- // When
- store {
- session.request(.default)
- .publishString()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanBePublishedUnserialized() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DataResponse<Data?, AFError>?
- // When
- store {
- AF.request(.default)
- .publishUnserialized()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanBePublishedWithMultipleHandlers() {
- // Given
- let handlerResponseReceived = expectation(description: "handler response should be received")
- let publishedResponseReceived = expectation(description: "published response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var handlerResponse: DataResponse<TestResponse, AFError>?
- var publishedResponse: DataResponse<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .responseDecodable(of: TestResponse.self) { handlerResponse = $0; handlerResponseReceived.fulfill() }
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { publishedResponse = $0; publishedResponseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(handlerResponse?.result.isSuccess == true)
- XCTAssertTrue(publishedResponse?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanPublishResult() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- .result()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { result = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(result?.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanPublishValue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var value: TestResponse?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- .value()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { value = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(value)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanPublishValueWithFailure() {
- // Given
- let completionReceived = expectation(description: "stream should complete")
- var error: AFError?
- // When
- store {
- AF.request(Endpoint(path: .delay(interval: 1), timeout: 0.01))
- .publishDecodable(type: TestResponse.self)
- .value()
- .sink(receiveCompletion: { completion in
- switch completion {
- case let .failure(err):
- error = err
- case .finished:
- error = nil
- }
- completionReceived.fulfill()
- }, receiveValue: { _ in })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(error)
- XCTAssertEqual((error?.underlyingError as? URLError)?.code, .timedOut)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatPublishedDataRequestIsNotResumedUnlessSubscribed() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DataResponse<TestResponse, AFError>?
- // When
- let request = AF.request(.default)
- let publisher = request.publishDecodable(type: TestResponse.self)
- let stateAfterPublisher = request.state
- store {
- publisher.sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- let stateAfterSubscription = request.state
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- XCTAssertEqual(stateAfterPublisher, .initialized)
- XCTAssertEqual(stateAfterSubscription, .resumed)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestCanSubscribedFromNonMainQueueButPublishedOnMainQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var receivedOnMain = false
- var response: DataResponse<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- .subscribe(on: queue)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: {
- receivedOnMain = Thread.isMainThread
- response = $0
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- XCTAssertTrue(receivedOnMain)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestPublishedOnSeparateQueueIsReceivedOnThatQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var response: DataResponse<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self, queue: queue)
- .sink(receiveCompletion: { _ in
- dispatchPrecondition(condition: .onQueue(queue))
- completionReceived.fulfill()
- },
- receiveValue: {
- dispatchPrecondition(condition: .onQueue(queue))
- response = $0
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDataRequestPublishedOnSeparateQueueCanBeReceivedOntoMainQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var receivedOnMain = false
- var response: DataResponse<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self, queue: queue)
- .receive(on: DispatchQueue.main)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: {
- receivedOnMain = Thread.isMainThread
- response = $0
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- XCTAssertTrue(receivedOnMain)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatPublishedDataRequestCanBeCancelledAutomatically() throws {
- if #available(macOS 11, iOS 14, watchOS 7, tvOS 14, *) {
- throw XCTSkip("Skip on 2020 OS versions, as Combine cancellation no longer emits a value.")
- }
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DataResponse<TestResponse, AFError>?
- // When
- let request = AF.request(.default)
- var token: AnyCancellable? = request
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- token = nil
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isFailure == true)
- XCTAssertTrue(response?.error?.isExplicitlyCancelledError == true,
- "error is not explicitly cancelled but \(response?.error?.localizedDescription ?? "None")")
- XCTAssertTrue(request.isCancelled)
- XCTAssertNil(token)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatPublishedDataRequestCanBeCancelledManually() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DataResponse<TestResponse, AFError>?
- // When
- let request = AF.request(.default)
- store {
- request
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- request.cancel()
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isFailure == true)
- XCTAssertTrue(response?.error?.isExplicitlyCancelledError == true,
- "error is not explicitly cancelled but \(response?.error?.localizedDescription ?? "None")")
- XCTAssertTrue(request.isCancelled)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatMultipleDataRequestPublishersCanBeCombined() {
- // Given
- let responseReceived = expectation(description: "combined response should be received")
- let completionReceived = expectation(description: "combined stream should complete")
- var firstResponse: DataResponse<TestResponse, AFError>?
- var secondResponse: DataResponse<TestResponse, AFError>?
- // When
- let first = AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- let second = AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- store {
- Publishers.CombineLatest(first, second)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() }) { first, second in
- firstResponse = first
- secondResponse = second
- responseReceived.fulfill()
- }
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(firstResponse?.result.isSuccess == true)
- XCTAssertTrue(secondResponse?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatMultipleDataRequestPublishersCanBeChained() {
- // Given
- let responseReceived = expectation(description: "combined response should be received")
- let completionReceived = expectation(description: "combined stream should complete")
- let customValue = "CustomValue"
- var firstResponse: DataResponse<TestResponse, AFError>?
- var secondResponse: DataResponse<TestResponse, AFError>?
- // When
- store {
- AF.request(.default)
- .publishDecodable(type: TestResponse.self)
- .flatMap { response -> DataResponsePublisher<TestResponse> in
- firstResponse = response
- let request = Endpoint(headers: ["X-Custom": customValue])
- return AF.request(request)
- .publishDecodable(type: TestResponse.self)
- }
- .sink(receiveCompletion: { _ in completionReceived.fulfill() }) { response in
- secondResponse = response
- responseReceived.fulfill()
- }
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(firstResponse?.result.isSuccess == true)
- XCTAssertTrue(secondResponse?.result.isSuccess == true)
- XCTAssertEqual(secondResponse?.value?.headers["X-Custom"], customValue)
- }
- }
- // MARK: - DataStreamRequest
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- final class DataStreamRequestCombineTests: CombineTestCase {
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanBePublished() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatNonAutomaticDataStreamRequestCanBePublished() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let session = Session(startRequestsImmediately: false)
- var result: Result<TestResponse, AFError>?
- // When
- store {
- session.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanPublishData() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<Data, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishData()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanPublishString() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<String, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishString()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanBePublishedWithMultipleHandlers() {
- // Given
- let handlerResponseReceived = expectation(description: "handler response should be received")
- let publishedResponseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var handlerResult: Result<TestResponse, AFError>?
- var publishedResult: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .responseStreamDecodable(of: TestResponse.self) { stream in
- switch stream.event {
- case let .stream(value):
- handlerResult = value
- case .complete:
- handlerResponseReceived.fulfill()
- }
- }
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- switch stream.event {
- case let .stream(value):
- publishedResult = value
- case .complete:
- publishedResponseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(handlerResult?.success)
- XCTAssertNotNil(publishedResult?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanPublishResult() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- .result()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { received in
- result = received
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanPublishResultWithResponseFailure() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(Endpoint.delay(1).modifying(\.timeout, to: 0.1))
- .publishDecodable(type: TestResponse.self)
- .result()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { received in
- result = received
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNil(result?.success)
- XCTAssertEqual((result?.failure?.underlyingError as? URLError)?.code, .timedOut)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanPublishValue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: TestResponse?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- .value()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { received in
- response = received
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(response)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanPublishValueWithFailure() {
- // Given
- let completionReceived = expectation(description: "stream should complete")
- var error: AFError?
- // When
- store {
- AF.streamRequest(Endpoint.delay(1).modifying(\.timeout, to: 0.1))
- .publishDecodable(type: TestResponse.self)
- .value()
- .sink(receiveCompletion: { completion in
- switch completion {
- case let .failure(err):
- error = err
- case .finished:
- error = nil
- }
- completionReceived.fulfill()
- }, receiveValue: { _ in })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(error)
- XCTAssertEqual((error?.underlyingError as? URLError)?.code, .timedOut)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatPublishedDataStreamRequestIsNotResumedUnlessSubscribed() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var result: Result<TestResponse, AFError>?
- // When
- let request = AF.streamRequest(.default)
- let publisher = request.publishDecodable(type: TestResponse.self)
- let stateAfterPublisher = request.state
- store {
- publisher.sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- let stateAfterSubscription = request.state
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(result?.isSuccess == true)
- XCTAssertEqual(stateAfterPublisher, .initialized)
- XCTAssertEqual(stateAfterSubscription, .resumed)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestCanSubscribedFromNonMainQueueButPublishedOnMainQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var receivedOnMain = false
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- .subscribe(on: queue)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- receivedOnMain = Thread.isMainThread
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- XCTAssertTrue(receivedOnMain)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestPublishedOnSeparateQueueIsReceivedOnThatQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self, queue: queue)
- .sink(receiveCompletion: { _ in
- dispatchPrecondition(condition: .onQueue(queue))
- completionReceived.fulfill()
- },
- receiveValue: { stream in
- dispatchPrecondition(condition: .onQueue(queue))
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatDataStreamRequestPublishedOnSeparateQueueCanBeReceivedOntoMainQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var receivedOnMain = false
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self, queue: queue)
- .receive(on: DispatchQueue.main)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { stream in
- receivedOnMain = Thread.isMainThread
- switch stream.event {
- case let .stream(value):
- result = value
- case .complete:
- responseReceived.fulfill()
- }
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(result?.success)
- XCTAssertTrue(receivedOnMain)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatPublishedDataStreamRequestCanBeCancelledAutomatically() throws {
- if #available(macOS 11, iOS 14, watchOS 7, tvOS 14, *) {
- throw XCTSkip("Skip on 2020 OS versions, as Combine cancellation no longer emits a value.")
- }
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var error: AFError?
- // When
- let request = AF.streamRequest(.default)
- var token: AnyCancellable? = request
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { error = $0.completion?.error; responseReceived.fulfill() })
- token = nil
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(error)
- XCTAssertTrue(error?.isExplicitlyCancelledError == true,
- "error is not explicitly cancelled but \(error?.localizedDescription ?? "None")")
- XCTAssertTrue(request.isCancelled)
- XCTAssertNil(token)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatPublishedDataStreamRequestCanBeCancelledManually() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var error: AFError?
- // When
- let request = AF.streamRequest(.default)
- store {
- request
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { error = $0.completion?.error; responseReceived.fulfill() })
- }
- request.cancel()
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(error)
- XCTAssertTrue(error?.isExplicitlyCancelledError == true,
- "error is not explicitly cancelled but \(error?.localizedDescription ?? "None")")
- XCTAssertTrue(request.isCancelled)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatMultipleDataStreamPublishersCanBeCombined() {
- // Given
- let responseReceived = expectation(description: "combined response should be received")
- let completionReceived = expectation(description: "combined stream should complete")
- var firstCompletion: DataStreamRequest.Completion?
- var secondCompletion: DataStreamRequest.Completion?
- // When
- let first = AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- let second = AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- store {
- Publishers.CombineLatest(first.compactMap(\.completion), second.compactMap(\.completion))
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { first, second in
- firstCompletion = first
- secondCompletion = second
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(firstCompletion)
- XCTAssertNotNil(secondCompletion)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- func testThatMultipleDataStreamRequestPublishersCanBeChained() {
- // Given
- let responseReceived = expectation(description: "combined response should be received")
- let completionReceived = expectation(description: "combined stream should complete")
- var firstCompletion: DataStreamRequest.Completion?
- var secondCompletion: DataStreamRequest.Completion?
- // When
- store {
- AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- .compactMap(\.completion)
- .flatMap { completion -> DataStreamPublisher<TestResponse> in
- firstCompletion = completion
- return AF.streamRequest(.default)
- .publishDecodable(type: TestResponse.self)
- }
- .compactMap(\.completion)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { secondCompletion = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(firstCompletion)
- XCTAssertNotNil(secondCompletion)
- }
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- final class DownloadRequestCombineTests: CombineTestCase {
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanBePublished() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatNonAutomaticDownloadRequestCanBePublished() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- let session = Session(startRequestsImmediately: false)
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- session.download(.default)
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishData() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- var response: DownloadResponse<Data, AFError>?
- // When
- store {
- AF.download(.default)
- .publishData()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishString() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- var response: DownloadResponse<String, AFError>?
- // When
- store {
- AF.download(.default)
- .publishString()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishUnserialized() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- var response: DownloadResponse<URL?, AFError>?
- // When
- store {
- AF.download(.default)
- .publishUnserialized()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishURL() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- var response: DownloadResponse<URL, AFError>?
- // When
- store {
- AF.download(.default)
- .publishURL()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishWithMultipleHandlers() {
- // Given
- let handlerResponseReceived = expectation(description: "handler response should be received")
- let publishedResponseReceived = expectation(description: "published response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var handlerResponse: DownloadResponse<TestResponse, AFError>?
- var publishedResponse: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .responseDecodable(of: TestResponse.self) { handlerResponse = $0; handlerResponseReceived.fulfill() }
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { publishedResponse = $0; publishedResponseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(handlerResponse?.result.isSuccess == true)
- XCTAssertTrue(publishedResponse?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishResult() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "publisher should complete")
- var result: Result<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .publishDecodable(type: TestResponse.self)
- .result()
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { result = $0; responseReceived.fulfill() })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(result?.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanPublishValueWithFailure() {
- // Given
- let completionReceived = expectation(description: "stream should complete")
- var error: AFError?
- // When
- store {
- AF.download(Endpoint.delay(1).modifying(\.timeout, to: 0.1))
- .publishDecodable(type: TestResponse.self)
- .value()
- .sink(receiveCompletion: { completion in
- switch completion {
- case let .failure(err):
- error = err
- case .finished:
- error = nil
- }
- completionReceived.fulfill()
- }, receiveValue: { _ in })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertNotNil(error)
- XCTAssertEqual((error?.underlyingError as? URLError)?.code, .timedOut)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatPublishedDownloadRequestIsNotResumedUnlessSubscribed() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- let request = AF.download(.default)
- let publisher = request.publishDecodable(type: TestResponse.self)
- let stateAfterPublisher = request.state
- store {
- publisher.sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- let stateAfterSubscription = request.state
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- XCTAssertEqual(stateAfterPublisher, .initialized)
- XCTAssertEqual(stateAfterSubscription, .resumed)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestCanSubscribedFromNonMainQueueButPublishedOnMainQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var receivedOnMain = false
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .publishDecodable(type: TestResponse.self)
- .subscribe(on: queue)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: {
- receivedOnMain = Thread.isMainThread
- response = $0
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- XCTAssertTrue(receivedOnMain)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestPublishedOnSeparateQueueIsReceivedOnThatQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .publishDecodable(type: TestResponse.self, queue: queue)
- .sink(receiveCompletion: { _ in
- dispatchPrecondition(condition: .onQueue(queue))
- completionReceived.fulfill()
- },
- receiveValue: {
- dispatchPrecondition(condition: .onQueue(queue))
- response = $0
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatDownloadRequestPublishedOnSeparateQueueCanBeReceivedOntoMainQueue() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- let queue = DispatchQueue(label: "org.alamofire.tests.combineEventQueue")
- var receivedOnMain = false
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .publishDecodable(type: TestResponse.self, queue: queue)
- .receive(on: DispatchQueue.main)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: {
- receivedOnMain = Thread.isMainThread
- response = $0
- responseReceived.fulfill()
- })
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isSuccess == true)
- XCTAssertTrue(receivedOnMain)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatPublishedDownloadRequestCanBeCancelledAutomatically() throws {
- if #available(macOS 11, iOS 14, watchOS 7, tvOS 14, *) {
- throw XCTSkip("Skip on 2020 OS versions, as Combine cancellation no longer emits a value.")
- }
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- let request = AF.download(.default)
- var token: AnyCancellable? = request
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- token = nil
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isFailure == true)
- XCTAssertTrue(response?.error?.isExplicitlyCancelledError == true,
- "error is not explicitly cancelled but \(response?.error?.localizedDescription ?? "None")")
- XCTAssertTrue(request.isCancelled)
- XCTAssertNil(token)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatPublishedDownloadRequestCanBeCancelledManually() {
- // Given
- let responseReceived = expectation(description: "response should be received")
- let completionReceived = expectation(description: "stream should complete")
- var response: DownloadResponse<TestResponse, AFError>?
- // When
- let request = AF.download(.default)
- store {
- request
- .publishDecodable(type: TestResponse.self)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() },
- receiveValue: { response = $0; responseReceived.fulfill() })
- }
- request.cancel()
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(response?.result.isFailure == true)
- XCTAssertTrue(response?.error?.isExplicitlyCancelledError == true,
- "error is not explicitly cancelled but \(response?.error?.localizedDescription ?? "None")")
- XCTAssertTrue(request.isCancelled)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatMultipleDownloadRequestPublishersCanBeCombined() {
- // Given
- let responseReceived = expectation(description: "combined response should be received")
- let completionReceived = expectation(description: "combined stream should complete")
- var firstResponse: DownloadResponse<TestResponse, AFError>?
- var secondResponse: DownloadResponse<TestResponse, AFError>?
- // When
- let first = AF.download(.default)
- .publishDecodable(type: TestResponse.self)
- let second = AF.download(.default)
- .publishDecodable(type: TestResponse.self)
- store {
- Publishers.CombineLatest(first, second)
- .sink(receiveCompletion: { _ in completionReceived.fulfill() }) { first, second in
- firstResponse = first
- secondResponse = second
- responseReceived.fulfill()
- }
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(firstResponse?.result.isSuccess == true)
- XCTAssertTrue(secondResponse?.result.isSuccess == true)
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- @MainActor
- func testThatMultipleDownloadRequestPublishersCanBeChained() {
- // Given
- let responseReceived = expectation(description: "combined response should be received")
- let completionReceived = expectation(description: "combined stream should complete")
- let customValue = "CustomValue"
- var firstResponse: DownloadResponse<TestResponse, AFError>?
- var secondResponse: DownloadResponse<TestResponse, AFError>?
- // When
- store {
- AF.download(.default)
- .publishDecodable(type: TestResponse.self)
- .flatMap { response -> DownloadResponsePublisher<TestResponse> in
- firstResponse = response
- let request = Endpoint(headers: ["X-Custom": customValue])
- return AF.download(request)
- .publishDecodable(type: TestResponse.self)
- }
- .sink(receiveCompletion: { _ in completionReceived.fulfill() }) { response in
- secondResponse = response
- responseReceived.fulfill()
- }
- }
- waitForExpectations(timeout: timeout)
- // Then
- XCTAssertTrue(firstResponse?.result.isSuccess == true)
- XCTAssertTrue(secondResponse?.result.isSuccess == true)
- XCTAssertEqual(secondResponse?.value?.headers["X-Custom"], customValue)
- }
- }
- @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
- class CombineTestCase: BaseTestCase {
- private lazy var storage: Set<AnyCancellable> = .init()
- override func tearDown() {
- storage.removeAll()
- super.tearDown()
- }
- func store(_ toStore: () -> AnyCancellable) {
- storage.insert(toStore())
- }
- }
- #endif
|