1+ import Alamofire
12import Foundation
23import Testing
34import ipinfoKit
45
6+ /// Custom URLProtocol that only mocks specific URLs for resproxy tests
7+ private class ResproxyMockURLProtocol : URLProtocol {
8+ nonisolated ( unsafe) static var mockResponses : [ String : Data ] = [ : ]
9+
10+ override class func canInit( with request: URLRequest ) -> Bool {
11+ guard let url = request. url? . absoluteString else { return false }
12+ return mockResponses. keys. contains ( url)
13+ }
14+
15+ override class func canonicalRequest( for request: URLRequest ) -> URLRequest {
16+ return request
17+ }
18+
19+ override func startLoading( ) {
20+ guard let url = request. url? . absoluteString,
21+ let data = ResproxyMockURLProtocol . mockResponses [ url] else {
22+ client? . urlProtocol ( self , didFailWithError: NSError ( domain: " ResproxyMockURLProtocol " , code: 404 ) )
23+ return
24+ }
25+
26+ let response = HTTPURLResponse ( url: request. url!, statusCode: 200 , httpVersion: " HTTP/1.1 " , headerFields: [ " Content-Type " : " application/json " ] ) !
27+ client? . urlProtocol ( self , didReceive: response, cacheStoragePolicy: . notAllowed)
28+ client? . urlProtocol ( self , didLoad: data)
29+ client? . urlProtocolDidFinishLoading ( self )
30+ }
31+
32+ override func stopLoading( ) { }
33+ }
34+
535@MainActor
636struct ResproxyTests {
37+
738 @Test func resproxyTest( ) async throws {
39+ // Set up mock response
40+ let mockData = """
41+ { " ip " : " 175.107.211.204 " , " last_seen " : " 2025-01-20 " , " percent_days_seen " :0.85, " service " : " example_service " }
42+ """ . data ( using: . utf8) !
43+ ResproxyMockURLProtocol . mockResponses [ " https://ipinfo.io/resproxy/175.107.211.204 " ] = mockData
44+
45+ // Configure mock session for this test
46+ let configuration = URLSessionConfiguration . ephemeral
47+ configuration. protocolClasses = [ ResproxyMockURLProtocol . self]
48+ let mockSession = Session ( configuration: configuration)
49+ Service . shared. session = mockSession
50+
851 let response = try await withCheckedThrowingContinuation { continuation in
952 IPINFO . shared. getResproxy ( ip: " 175.107.211.204 " ) { status, response, msg in
1053 switch status {
@@ -26,13 +69,26 @@ struct ResproxyTests {
2669 }
2770 }
2871
72+ Service . shared. session = nil
73+ ResproxyMockURLProtocol . mockResponses. removeAll ( )
74+
2975 #expect( response. ip == " 175.107.211.204 " )
30- #expect( response. lastSeen != nil )
31- #expect( response. percentDaysSeen != nil )
32- #expect( response. service != nil )
76+ #expect( response. lastSeen == " 2025-01-20 " )
77+ #expect( response. percentDaysSeen == 0.85 )
78+ #expect( response. service == " example_service " )
3379 }
3480
3581 @Test func resproxyEmptyTest( ) async throws {
82+ // Set up mock response for empty result
83+ let mockData = " {} " . data ( using: . utf8) !
84+ ResproxyMockURLProtocol . mockResponses [ " https://ipinfo.io/resproxy/8.8.8.8 " ] = mockData
85+
86+ // Configure mock session for this test
87+ let configuration = URLSessionConfiguration . ephemeral
88+ configuration. protocolClasses = [ ResproxyMockURLProtocol . self]
89+ let mockSession = Session ( configuration: configuration)
90+ Service . shared. session = mockSession
91+
3692 let response = try await withCheckedThrowingContinuation { continuation in
3793 IPINFO . shared. getResproxy ( ip: " 8.8.8.8 " ) { status, response, msg in
3894 switch status {
@@ -54,6 +110,9 @@ struct ResproxyTests {
54110 }
55111 }
56112
113+ Service . shared. session = nil
114+ ResproxyMockURLProtocol . mockResponses. removeAll ( )
115+
57116 #expect( response. ip == nil )
58117 #expect( response. lastSeen == nil )
59118 #expect( response. percentDaysSeen == nil )
0 commit comments