From ff551c9a5fed2f6b5642965d7950a24fcd3f1dd2 Mon Sep 17 00:00:00 2001 From: Madeline Date: Wed, 22 Feb 2023 20:14:11 -0500 Subject: [PATCH] Externalize NWBrowser dependency in PrinterRequestManager into protocol for testing --- Soyuz.xcodeproj/project.pbxproj | 4 +++ Soyuz/PrinterRequestManager.swift | 38 ++++++++++++++++---- SoyuzTests/PrinterRequestsManagerTests.swift | 24 +++++++++++++ SoyuzTests/SoyuzTests.swift | 30 ++++++++-------- SoyuzUITests/SoyuzUITests.swift | 32 ++++++++--------- SoyuzUITests/SoyuzUITestsLaunchTests.swift | 24 ++++++------- 6 files changed, 102 insertions(+), 50 deletions(-) create mode 100644 SoyuzTests/PrinterRequestsManagerTests.swift diff --git a/Soyuz.xcodeproj/project.pbxproj b/Soyuz.xcodeproj/project.pbxproj index a1b0f43..8a7d829 100644 --- a/Soyuz.xcodeproj/project.pbxproj +++ b/Soyuz.xcodeproj/project.pbxproj @@ -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 = ""; }; E124B9D829941A4D00C0D2D2 /* PrinterConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrinterConfigView.swift; sourceTree = ""; }; E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoyuzScratchTests.swift; sourceTree = ""; }; + E16378B329A491E6002F05E9 /* PrinterRequestsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrinterRequestsManagerTests.swift; sourceTree = ""; }; 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 = ""; }; E180B5EC2992CD9200425DB0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -141,6 +143,7 @@ children = ( E180B5FF2992CD9300425DB0 /* SoyuzTests.swift */, E16378B129A43CE1002F05E9 /* SoyuzScratchTests.swift */, + E16378B329A491E6002F05E9 /* PrinterRequestsManagerTests.swift */, ); path = SoyuzTests; sourceTree = ""; @@ -306,6 +309,7 @@ buildActionMask = 2147483647; files = ( E180B6002992CD9300425DB0 /* SoyuzTests.swift in Sources */, + E16378B429A491E6002F05E9 /* PrinterRequestsManagerTests.swift in Sources */, E16378B229A43CE1002F05E9 /* SoyuzScratchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Soyuz/PrinterRequestManager.swift b/Soyuz/PrinterRequestManager.swift index 876e63b..d37ea9a 100644 --- a/Soyuz/PrinterRequestManager.swift +++ b/Soyuz/PrinterRequestManager.swift @@ -9,6 +9,28 @@ import Foundation import Network import Starscream +// MARK: Bonjour Protocol + +protocol NetworkDiscoveryEngine { + func startScan(queue: DispatchQueue) + func setBrowseResultsChangedHandler(_ handler: @escaping ((Set, Set) -> Void)) + func setStateUpdateHandler(_ handler: @escaping ((NWBrowser.State) -> Void)) +} + +extension NWBrowser: NetworkDiscoveryEngine { + func startScan(queue: DispatchQueue) { + start(queue: queue) + } + func setBrowseResultsChangedHandler(_ handler: @escaping ((Set, Set) -> 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. diff --git a/SoyuzTests/PrinterRequestsManagerTests.swift b/SoyuzTests/PrinterRequestsManagerTests.swift new file mode 100644 index 0000000..5d73f97 --- /dev/null +++ b/SoyuzTests/PrinterRequestsManagerTests.swift @@ -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 + } + +} diff --git a/SoyuzTests/SoyuzTests.swift b/SoyuzTests/SoyuzTests.swift index 1a3f297..26b1543 100644 --- a/SoyuzTests/SoyuzTests.swift +++ b/SoyuzTests/SoyuzTests.swift @@ -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. +// } +// } } diff --git a/SoyuzUITests/SoyuzUITests.swift b/SoyuzUITests/SoyuzUITests.swift index b6fc433..f444a4e 100644 --- a/SoyuzUITests/SoyuzUITests.swift +++ b/SoyuzUITests/SoyuzUITests.swift @@ -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() +// } +// } +// } } diff --git a/SoyuzUITests/SoyuzUITestsLaunchTests.swift b/SoyuzUITests/SoyuzUITestsLaunchTests.swift index 0abcc11..a219c0a 100644 --- a/SoyuzUITests/SoyuzUITestsLaunchTests.swift +++ b/SoyuzUITests/SoyuzUITestsLaunchTests.swift @@ -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) +// } }