// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import Foundation import Combine import SessionUtilitiesKit // MARK: - MockNetwork class MockNetwork: Mock, NetworkType { var requestData: RequestData? func send(_ request: Network.RequestType) -> AnyPublisher<(ResponseInfoType, T), Error> { requestData = request.data return accept(funcName: "send(\(request.id))", args: request.args) as! AnyPublisher<(ResponseInfoType, T), Error> } static func response(info: MockResponseInfo = .mockValue, with value: T) -> AnyPublisher<(ResponseInfoType, Data?), Error> { return Just((info, try? JSONEncoder().with(outputFormatting: .sortedKeys).encode(value))) .setFailureType(to: Error.self) .eraseToAnyPublisher() } static func response(info: MockResponseInfo = .mockValue, type: T.Type) -> AnyPublisher<(ResponseInfoType, Data?), Error> { return response(info: info, with: T.mockValue) } static func response(info: MockResponseInfo = .mockValue, type: Array.Type) -> AnyPublisher<(ResponseInfoType, Data?), Error> { return response(info: info, with: [T.mockValue]) } static func batchResponseData( info: MockResponseInfo = .mockValue, with value: [(endpoint: E, data: Data)] ) -> AnyPublisher<(ResponseInfoType, Data?), Error> { let data: Data = "[\(value.map { String(data: $0.data, encoding: .utf8)! }.joined(separator: ","))]" .data(using: .utf8)! return Just((info, data)) .setFailureType(to: Error.self) .eraseToAnyPublisher() } static func response(info: MockResponseInfo = .mockValue, data: Data) -> AnyPublisher<(ResponseInfoType, Data?), Error> { return Just((info, data)) .setFailureType(to: Error.self) .eraseToAnyPublisher() } static func nullResponse(info: MockResponseInfo = .mockValue) -> AnyPublisher<(ResponseInfoType, Data?), Error> { return Just((info, nil)) .setFailureType(to: Error.self) .eraseToAnyPublisher() } } // MARK: - MockResponseInfo struct MockResponseInfo: ResponseInfoType, Mocked { static let mockValue: MockResponseInfo = MockResponseInfo(requestData: .fallbackData, code: 200, headers: [:]) let requestData: RequestData let code: Int let headers: [String: String] init(requestData: RequestData, code: Int, headers: [String: String]) { self.requestData = requestData self.code = code self.headers = headers } } struct RequestData: Codable { static let fallbackData: RequestData = RequestData(urlString: nil, httpMethod: "GET", headers: [:], body: nil) let urlString: String? let httpMethod: String let headers: [String: String] let body: Data? } extension Network.RequestType { var data: RequestData { return RequestData( urlString: url, httpMethod: (method ?? ""), headers: (headers ?? [:]), body: body ) } } // MARK: - HTTP.BatchSubResponse Encoding Convenience extension Encodable where Self: Codable { func batchSubResponse() -> Data { return try! JSONEncoder().with(outputFormatting: .sortedKeys).encode( HTTP.BatchSubResponse( code: 200, headers: [:], body: self, failedToParseBody: false ) ) } } extension Mocked where Self: Codable { static func mockBatchSubResponse() -> Data { return mockValue.batchSubResponse() } } extension Array where Element: Mocked, Element: Codable { static func mockBatchSubResponse() -> Data { return [Element.mockValue].batchSubResponse() } }