@@ -10,6 +10,7 @@ import Foundation
1010
1111enum URLProtocolMockError : Error {
1212 case unexpectedRequest
13+ case simulatedTransportFailure
1314}
1415
1516class URLProtocolMock : URLProtocol {
@@ -71,3 +72,47 @@ class URLProtocolAuthenticationMock: URLProtocol, URLAuthenticationChallengeSend
7172
7273 override func stopLoading( ) { }
7374}
75+
76+ /// Test-only `URLProtocol` that emits a queued sequence of either HTTP responses or auth challenges
77+ /// in order. Used to target an auth challenge at a specific request (e.g. the transfer task) while
78+ /// letting earlier requests (e.g. the preflight `PROPFIND`) resolve normally.
79+ class URLProtocolSequenceMock : URLProtocol , URLAuthenticationChallengeSender {
80+ enum Step {
81+ case response( HTTPURLResponse , Data ? )
82+ case authChallenge( URLAuthenticationChallengeMock )
83+ }
84+
85+ func use( _ credential: URLCredential , for challenge: URLAuthenticationChallenge ) { }
86+
87+ func continueWithoutCredential( for challenge: URLAuthenticationChallenge ) { }
88+
89+ func cancel( _ challenge: URLAuthenticationChallenge ) { }
90+
91+ static var steps = [ Step] ( )
92+
93+ override func startLoading( ) {
94+ let step = URLProtocolSequenceMock . steps. removeFirst ( )
95+ switch step {
96+ case let . response( response, data) :
97+ client? . urlProtocol ( self , didReceive: response, cacheStoragePolicy: . notAllowed)
98+ if let data = data {
99+ client? . urlProtocol ( self , didLoad: data)
100+ }
101+ client? . urlProtocolDidFinishLoading ( self )
102+ case let . authChallenge( settings) :
103+ let protectionSpace = URLProtectionSpace ( host: " " , port: 443 , protocol: nil , realm: nil , authenticationMethod: nil )
104+ let challenge = URLAuthenticationChallenge ( protectionSpace: protectionSpace, proposedCredential: nil , previousFailureCount: settings. previousFailureCount, failureResponse: settings. failureResponse, error: nil , sender: self )
105+ client? . urlProtocol ( self , didReceive: challenge)
106+ }
107+ }
108+
109+ override class func canInit( with request: URLRequest ) -> Bool {
110+ return true
111+ }
112+
113+ override class func canonicalRequest( for request: URLRequest ) -> URLRequest {
114+ return request
115+ }
116+
117+ override func stopLoading( ) { }
118+ }
0 commit comments