Externalize NWBrowser dependency in PrinterRequestManager into protocol for testing
This commit is contained in:
		@@ -9,6 +9,7 @@
 | 
			
		||||
/* Begin PBXBuildFile section */
 | 
			
		||||
		E124B9D929941A4D00C0D2D2 /* PrinterConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E124B9D829941A4D00C0D2D2 /* PrinterConfigView.swift */; };
 | 
			
		||||
		E16378B229A43CE1002F05E9 /* SoyuzScratchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */; };
 | 
			
		||||
		E16378B429A491E6002F05E9 /* PrinterRequestsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16378B329A491E6002F05E9 /* PrinterRequestsManagerTests.swift */; };
 | 
			
		||||
		E180B5E92992CD9100425DB0 /* SoyuzApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E180B5E82992CD9100425DB0 /* SoyuzApp.swift */; };
 | 
			
		||||
		E180B5ED2992CD9200425DB0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E180B5EC2992CD9200425DB0 /* Assets.xcassets */; };
 | 
			
		||||
		E180B5F02992CD9200425DB0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E180B5EF2992CD9200425DB0 /* Preview Assets.xcassets */; };
 | 
			
		||||
@@ -45,6 +46,7 @@
 | 
			
		||||
		E124B9D72993FE5500C0D2D2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
 | 
			
		||||
		E124B9D829941A4D00C0D2D2 /* PrinterConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrinterConfigView.swift; sourceTree = "<group>"; };
 | 
			
		||||
		E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoyuzScratchTests.swift; sourceTree = "<group>"; };
 | 
			
		||||
		E16378B329A491E6002F05E9 /* PrinterRequestsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrinterRequestsManagerTests.swift; sourceTree = "<group>"; };
 | 
			
		||||
		E180B5E52992CD9100425DB0 /* Soyuz.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Soyuz.app; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
			
		||||
		E180B5E82992CD9100425DB0 /* SoyuzApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoyuzApp.swift; sourceTree = "<group>"; };
 | 
			
		||||
		E180B5EC2992CD9200425DB0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 | 
			
		||||
@@ -141,6 +143,7 @@
 | 
			
		||||
			children = (
 | 
			
		||||
				E180B5FF2992CD9300425DB0 /* SoyuzTests.swift */,
 | 
			
		||||
				E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */,
 | 
			
		||||
				E16378B329A491E6002F05E9 /* PrinterRequestsManagerTests.swift */,
 | 
			
		||||
			);
 | 
			
		||||
			path = SoyuzTests;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
@@ -306,6 +309,7 @@
 | 
			
		||||
			buildActionMask = 2147483647;
 | 
			
		||||
			files = (
 | 
			
		||||
				E180B6002992CD9300425DB0 /* SoyuzTests.swift in Sources */,
 | 
			
		||||
				E16378B429A491E6002F05E9 /* PrinterRequestsManagerTests.swift in Sources */,
 | 
			
		||||
				E16378B229A43CE1002F05E9 /* SoyuzScratchTests.swift in Sources */,
 | 
			
		||||
			);
 | 
			
		||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,28 @@ import Foundation
 | 
			
		||||
import Network
 | 
			
		||||
import Starscream
 | 
			
		||||
 | 
			
		||||
// MARK: Bonjour Protocol
 | 
			
		||||
 | 
			
		||||
protocol NetworkDiscoveryEngine {
 | 
			
		||||
    func startScan(queue: DispatchQueue)
 | 
			
		||||
    func setBrowseResultsChangedHandler(_ handler: @escaping ((Set<NWBrowser.Result>, Set<NWBrowser.Result.Change>) -> Void))
 | 
			
		||||
    func setStateUpdateHandler(_ handler: @escaping ((NWBrowser.State) -> Void))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extension NWBrowser: NetworkDiscoveryEngine {
 | 
			
		||||
    func startScan(queue: DispatchQueue) {
 | 
			
		||||
        start(queue: queue)
 | 
			
		||||
    }
 | 
			
		||||
    func setBrowseResultsChangedHandler(_ handler: @escaping ((Set<NWBrowser.Result>, Set<NWBrowser.Result.Change>) -> Void)) {
 | 
			
		||||
        self.browseResultsChangedHandler = handler
 | 
			
		||||
    }
 | 
			
		||||
    func setStateUpdateHandler(_ handler: @escaping ((State) -> Void)) {
 | 
			
		||||
        self.stateUpdateHandler = handler
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MARK: Starscream Protocol
 | 
			
		||||
 | 
			
		||||
struct JsonRpcRequest: Codable {
 | 
			
		||||
    var jsonrpc = "2.0"
 | 
			
		||||
    let method: String
 | 
			
		||||
@@ -67,7 +89,8 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
 | 
			
		||||
    @Published var socketHost: String
 | 
			
		||||
    @Published var socketPort: String
 | 
			
		||||
    
 | 
			
		||||
    let nwBrowser = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp)
 | 
			
		||||
    let nwBrowser: NetworkDiscoveryEngine
 | 
			
		||||
    //let nwBrowser = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp)
 | 
			
		||||
    var connection: NWConnection!
 | 
			
		||||
    
 | 
			
		||||
    var socket: WebSocket?
 | 
			
		||||
@@ -101,13 +124,14 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private init() {
 | 
			
		||||
    private init(browser: NetworkDiscoveryEngine = NWBrowser(for: .bonjourWithTXTRecord(type: "_moonraker._tcp", domain: "local."), using: .tcp)) {
 | 
			
		||||
        state = ""
 | 
			
		||||
        progress = 0.0
 | 
			
		||||
        extruderTemperature = 0.0
 | 
			
		||||
        bedTemperature = 0.0
 | 
			
		||||
        socketHost = ""
 | 
			
		||||
        socketPort = ""
 | 
			
		||||
        nwBrowser = browser
 | 
			
		||||
        //reconnectionTimer = nil
 | 
			
		||||
        
 | 
			
		||||
        // MARK: Debug stuff
 | 
			
		||||
@@ -121,15 +145,15 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // MARK: Bonjour browser initialization at instantiation
 | 
			
		||||
        nwBrowser.browseResultsChangedHandler = { (newResults, changes) in
 | 
			
		||||
        nwBrowser.setBrowseResultsChangedHandler({ (newResults, changes) in
 | 
			
		||||
            print("[update] Results changed.")
 | 
			
		||||
            newResults.forEach { result in
 | 
			
		||||
                print(result)
 | 
			
		||||
                self.nwBrowserDiscoveredItems.append(result)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        })
 | 
			
		||||
        // Bonjour browser state update handler
 | 
			
		||||
        nwBrowser.stateUpdateHandler = { newState in
 | 
			
		||||
        nwBrowser.setStateUpdateHandler({ newState in
 | 
			
		||||
            switch newState {
 | 
			
		||||
            case .failed(let error):
 | 
			
		||||
                print("[error] nwbrowser: \(error)")
 | 
			
		||||
@@ -140,9 +164,9 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
 | 
			
		||||
            default:
 | 
			
		||||
                break
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        })
 | 
			
		||||
        // Start up the bonjour browser, get results and process them in the update handler
 | 
			
		||||
        nwBrowser.start(queue: DispatchQueue.main)
 | 
			
		||||
        nwBrowser.startScan(queue: DispatchQueue.main)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Called from the UI with an endpoint.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								SoyuzTests/PrinterRequestsManagerTests.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								SoyuzTests/PrinterRequestsManagerTests.swift
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
//
 | 
			
		||||
//  PrinterRequestsManagerTests.swift
 | 
			
		||||
//  SoyuzTests
 | 
			
		||||
//
 | 
			
		||||
//  Created by maddiefuzz on 2/21/23.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
import XCTest
 | 
			
		||||
@testable import Soyuz
 | 
			
		||||
 | 
			
		||||
class FileHandleMock: FileHandle {
 | 
			
		||||
    override func write(_ data: Data) {
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class PrinterRequestManagerTests: XCTestCase {
 | 
			
		||||
    var printerRequestsManager: PrinterRequestManager?
 | 
			
		||||
    
 | 
			
		||||
    override func setUp() {
 | 
			
		||||
        printerRequestsManager = PrinterRequestManager.shared
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
import XCTest
 | 
			
		||||
@testable import KlipperMon
 | 
			
		||||
@testable import Soyuz
 | 
			
		||||
 | 
			
		||||
final class SoyuzTests: XCTestCase {
 | 
			
		||||
 | 
			
		||||
@@ -18,19 +18,19 @@ final class SoyuzTests: XCTestCase {
 | 
			
		||||
        // Put teardown code here. This method is called after the invocation of each test method in the class.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func testExample() throws {
 | 
			
		||||
        // This is an example of a functional test case.
 | 
			
		||||
        // Use XCTAssert and related functions to verify your tests produce the correct results.
 | 
			
		||||
        // Any test you write for XCTest can be annotated as throws and async.
 | 
			
		||||
        // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
 | 
			
		||||
        // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func testPerformanceExample() throws {
 | 
			
		||||
        // This is an example of a performance test case.
 | 
			
		||||
        self.measure {
 | 
			
		||||
            // Put the code you want to measure the time of here.
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
//    func testExample() throws {
 | 
			
		||||
//        // This is an example of a functional test case.
 | 
			
		||||
//        // Use XCTAssert and related functions to verify your tests produce the correct results.
 | 
			
		||||
//        // Any test you write for XCTest can be annotated as throws and async.
 | 
			
		||||
//        // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
 | 
			
		||||
//        // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
 | 
			
		||||
//    }
 | 
			
		||||
//
 | 
			
		||||
//    func testPerformanceExample() throws {
 | 
			
		||||
//        // This is an example of a performance test case.
 | 
			
		||||
//        self.measure {
 | 
			
		||||
//            // Put the code you want to measure the time of here.
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,20 +22,20 @@ final class KlipperMonUITests: XCTestCase {
 | 
			
		||||
        // Put teardown code here. This method is called after the invocation of each test method in the class.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func testExample() throws {
 | 
			
		||||
        // UI tests must launch the application that they test.
 | 
			
		||||
        let app = XCUIApplication()
 | 
			
		||||
        app.launch()
 | 
			
		||||
 | 
			
		||||
        // Use XCTAssert and related functions to verify your tests produce the correct results.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func testLaunchPerformance() throws {
 | 
			
		||||
        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
 | 
			
		||||
            // This measures how long it takes to launch your application.
 | 
			
		||||
            measure(metrics: [XCTApplicationLaunchMetric()]) {
 | 
			
		||||
                XCUIApplication().launch()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
//    func testExample() throws {
 | 
			
		||||
//        // UI tests must launch the application that they test.
 | 
			
		||||
//        let app = XCUIApplication()
 | 
			
		||||
//        app.launch()
 | 
			
		||||
//
 | 
			
		||||
//        // Use XCTAssert and related functions to verify your tests produce the correct results.
 | 
			
		||||
//    }
 | 
			
		||||
//
 | 
			
		||||
//    func testLaunchPerformance() throws {
 | 
			
		||||
//        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
 | 
			
		||||
//            // This measures how long it takes to launch your application.
 | 
			
		||||
//            measure(metrics: [XCTApplicationLaunchMetric()]) {
 | 
			
		||||
//                XCUIApplication().launch()
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,16 +17,16 @@ final class KlipperMonUITestsLaunchTests: XCTestCase {
 | 
			
		||||
        continueAfterFailure = false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func testLaunch() throws {
 | 
			
		||||
        let app = XCUIApplication()
 | 
			
		||||
        app.launch()
 | 
			
		||||
 | 
			
		||||
        // Insert steps here to perform after app launch but before taking a screenshot,
 | 
			
		||||
        // such as logging into a test account or navigating somewhere in the app
 | 
			
		||||
 | 
			
		||||
        let attachment = XCTAttachment(screenshot: app.screenshot())
 | 
			
		||||
        attachment.name = "Launch Screen"
 | 
			
		||||
        attachment.lifetime = .keepAlways
 | 
			
		||||
        add(attachment)
 | 
			
		||||
    }
 | 
			
		||||
//    func testLaunch() throws {
 | 
			
		||||
//        let app = XCUIApplication()
 | 
			
		||||
//        app.launch()
 | 
			
		||||
//
 | 
			
		||||
//        // Insert steps here to perform after app launch but before taking a screenshot,
 | 
			
		||||
//        // such as logging into a test account or navigating somewhere in the app
 | 
			
		||||
//
 | 
			
		||||
//        let attachment = XCTAttachment(screenshot: app.screenshot())
 | 
			
		||||
//        attachment.name = "Launch Screen"
 | 
			
		||||
//        attachment.lifetime = .keepAlways
 | 
			
		||||
//        add(attachment)
 | 
			
		||||
//    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user