Repository: Alamofire/Alamofire
File: Tests/SessionTests.swift (Swift)

Code before:
        }
        session = nil

        waitForExpectations(timeout: timeout, handler: nil)

        // Then
        assertErrorIsAFError(error) { XCTAssertTrue($0.isSessionDeinitializedError) }
    }
}

// MARK: -

class SessionManagerConfigurationHeadersTestCase: BaseTestCase {
    enum ConfigurationType {
        case `default`, ephemeral, background
    }

    func testThatDefaultConfigurationHeadersAreSentWithRequest() {
        // Given, When, Then
        executeAuthorizationHeaderTest(for: .default)
    }

    func testThatEphemeralConfigurationHeadersAreSentWithRequest() {
        // Given, When, Then
        executeAuthorizationHeaderTest(for: .ephemeral)
    }
#if os(macOS)
    func testThatBackgroundConfigurationHeadersAreSentWithRequest() {
        // Given, When, Then
        executeAuthorizationHeaderTest(for: .background)
    }
#endif

    private func executeAuthorizationHeaderTest(for type: ConfigurationType) {
        // Given
        let session: Session = {
            let configuration: URLSessionConfiguration = {
                let configuration: URLSessionConfiguration

                switch type {
                case .default:
                    configuration = .default
                case .ephemeral:
                    configuration = .ephemeral
                case .background:
                    let identifier = "org.alamofire.test.manager-configuration-tests"
                    configuration = .background(withIdentifier: identifier)
                }

                var headers = HTTPHeaders.default
                headers["Authorization"] = "Bearer 123456"

Review comment (suggestion):
It seems like we may want to more generally fix `cancel()` by preventing its actions when the `Request` has already finished. It may be out of scope for this fix, but it makes sense to me that we may want to add an additional stage to state, perhaps `.completed`, to indicate that a `Request` has finished and started calling its completion handlers.

Code after:
        }
        session = nil

        waitForExpectations(timeout: timeout, handler: nil)

        // Then
        assertErrorIsAFError(error) { XCTAssertTrue($0.isSessionDeinitializedError) }
    }

    // MARK: Tests - Request Cancellation

    func testThatSessionOnlyCallsResponseSerializerCompletionWhenCancellingInsideCompletion() {
        // Given
        let handler = RequestHandler()
        let session = Session()

        let expectation = self.expectation(description: "request should complete")
        var response: DataResponse<Any>?
        var completionCallCount = 0

        // When
        let request = session.request("https://httpbin.org/get", interceptor: handler)
        request.validate()

        request.responseJSON { resp in
            request.cancel()

            response = resp
            completionCallCount += 1

            DispatchQueue.main.after(0.01) { expectation.fulfill() }
        }

        waitForExpectations(timeout: timeout, handler: nil)

        // Then
        XCTAssertEqual(handler.adaptCalledCount, 1)
        XCTAssertEqual(handler.adaptedCount, 1)
        XCTAssertEqual(handler.retryCalledCount, 0)
        XCTAssertEqual(handler.retryCount, 0)
        XCTAssertEqual(request.retryCount, 0)
        XCTAssertEqual(response?.result.isSuccess, true)
        XCTAssertTrue(session.requestTaskMap.isEmpty)
        XCTAssertEqual(completionCallCount, 1)
    }
}

// MARK: -

class SessionManagerConfigurationHeadersTestCase: BaseTestCase {
    enum ConfigurationType {