Externalize NWBrowser dependency in PrinterRequestManager into protocol for testing

This commit is contained in:
Madeline 2023-02-22 20:14:11 -05:00
parent 65daae4bf7
commit ff551c9a5f
6 changed files with 102 additions and 50 deletions

View File

@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
E124B9D929941A4D00C0D2D2 /* PrinterConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E124B9D829941A4D00C0D2D2 /* PrinterConfigView.swift */; }; E124B9D929941A4D00C0D2D2 /* PrinterConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E124B9D829941A4D00C0D2D2 /* PrinterConfigView.swift */; };
E16378B229A43CE1002F05E9 /* SoyuzScratchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16378B129A43CE1002F05E9 /* SoyuzScratchTests.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 */; }; E180B5E92992CD9100425DB0 /* SoyuzApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E180B5E82992CD9100425DB0 /* SoyuzApp.swift */; };
E180B5ED2992CD9200425DB0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E180B5EC2992CD9200425DB0 /* Assets.xcassets */; }; E180B5ED2992CD9200425DB0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E180B5EC2992CD9200425DB0 /* Assets.xcassets */; };
E180B5F02992CD9200425DB0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E180B5EF2992CD9200425DB0 /* Preview 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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; E180B5EC2992CD9200425DB0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -141,6 +143,7 @@
children = ( children = (
E180B5FF2992CD9300425DB0 /* SoyuzTests.swift */, E180B5FF2992CD9300425DB0 /* SoyuzTests.swift */,
E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */, E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */,
E16378B329A491E6002F05E9 /* PrinterRequestsManagerTests.swift */,
); );
path = SoyuzTests; path = SoyuzTests;
sourceTree = "<group>"; sourceTree = "<group>";
@ -306,6 +309,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
E180B6002992CD9300425DB0 /* SoyuzTests.swift in Sources */, E180B6002992CD9300425DB0 /* SoyuzTests.swift in Sources */,
E16378B429A491E6002F05E9 /* PrinterRequestsManagerTests.swift in Sources */,
E16378B229A43CE1002F05E9 /* SoyuzScratchTests.swift in Sources */, E16378B229A43CE1002F05E9 /* SoyuzScratchTests.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -9,6 +9,28 @@ import Foundation
import Network import Network
import Starscream 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 { struct JsonRpcRequest: Codable {
var jsonrpc = "2.0" var jsonrpc = "2.0"
let method: String let method: String
@ -67,7 +89,8 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
@Published var socketHost: String @Published var socketHost: String
@Published var socketPort: 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 connection: NWConnection!
var socket: WebSocket? 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 = "" state = ""
progress = 0.0 progress = 0.0
extruderTemperature = 0.0 extruderTemperature = 0.0
bedTemperature = 0.0 bedTemperature = 0.0
socketHost = "" socketHost = ""
socketPort = "" socketPort = ""
nwBrowser = browser
//reconnectionTimer = nil //reconnectionTimer = nil
// MARK: Debug stuff // MARK: Debug stuff
@ -121,15 +145,15 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
} }
// MARK: Bonjour browser initialization at instantiation // MARK: Bonjour browser initialization at instantiation
nwBrowser.browseResultsChangedHandler = { (newResults, changes) in nwBrowser.setBrowseResultsChangedHandler({ (newResults, changes) in
print("[update] Results changed.") print("[update] Results changed.")
newResults.forEach { result in newResults.forEach { result in
print(result) print(result)
self.nwBrowserDiscoveredItems.append(result) self.nwBrowserDiscoveredItems.append(result)
} }
} })
// Bonjour browser state update handler // Bonjour browser state update handler
nwBrowser.stateUpdateHandler = { newState in nwBrowser.setStateUpdateHandler({ newState in
switch newState { switch newState {
case .failed(let error): case .failed(let error):
print("[error] nwbrowser: \(error)") print("[error] nwbrowser: \(error)")
@ -140,9 +164,9 @@ class PrinterRequestManager: ObservableObject, WebSocketDelegate {
default: default:
break break
} }
} })
// Start up the bonjour browser, get results and process them in the update handler // 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. // Called from the UI with an endpoint.

View 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
}
}

View File

@ -6,7 +6,7 @@
// //
import XCTest import XCTest
@testable import KlipperMon @testable import Soyuz
final class SoyuzTests: XCTestCase { 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. // Put teardown code here. This method is called after the invocation of each test method in the class.
} }
func testExample() throws { // func testExample() throws {
// This is an example of a functional test case. // // This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results. // // 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. // // 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 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. // // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
} // }
//
func testPerformanceExample() throws { // func testPerformanceExample() throws {
// This is an example of a performance test case. // // This is an example of a performance test case.
self.measure { // self.measure {
// Put the code you want to measure the time of here. // // Put the code you want to measure the time of here.
} // }
} // }
} }

View File

@ -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. // Put teardown code here. This method is called after the invocation of each test method in the class.
} }
func testExample() throws { // func testExample() throws {
// UI tests must launch the application that they test. // // UI tests must launch the application that they test.
let app = XCUIApplication() // let app = XCUIApplication()
app.launch() // app.launch()
//
// Use XCTAssert and related functions to verify your tests produce the correct results. // // Use XCTAssert and related functions to verify your tests produce the correct results.
} // }
//
func testLaunchPerformance() throws { // func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { // if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
// This measures how long it takes to launch your application. // // This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) { // measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch() // XCUIApplication().launch()
} // }
} // }
} // }
} }

View File

@ -17,16 +17,16 @@ final class KlipperMonUITestsLaunchTests: XCTestCase {
continueAfterFailure = false continueAfterFailure = false
} }
func testLaunch() throws { // func testLaunch() throws {
let app = XCUIApplication() // let app = XCUIApplication()
app.launch() // app.launch()
//
// Insert steps here to perform after app launch but before taking a screenshot, // // 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 // // such as logging into a test account or navigating somewhere in the app
//
let attachment = XCTAttachment(screenshot: app.screenshot()) // let attachment = XCTAttachment(screenshot: app.screenshot())
attachment.name = "Launch Screen" // attachment.name = "Launch Screen"
attachment.lifetime = .keepAlways // attachment.lifetime = .keepAlways
add(attachment) // add(attachment)
} // }
} }