@rdlabo/capacitor-brotherprint 8.2.2 → 8.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/docs.json +1 -1
- package/dist/esm/interfaces.d.ts +2 -1
- package/dist/esm/interfaces.js.map +1 -1
- package/docs/search.md +4 -2
- package/ios/Sources/BrotherPrintPlugin/BrotherPrintPlugin.swift +81 -26
- package/ios/Tests/BrotherPrintPluginTests/BrotherPrintPluginTests.swift +83 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -289,7 +289,7 @@ These are optional. If these are not set, default values are assigned by the pri
|
|
|
289
289
|
|
|
290
290
|
#### BRLMSearchOption
|
|
291
291
|
|
|
292
|
-
<code>{ /** * 'usb' is android only, and now developing. */ port: <a href="#brlmprinterport">BRLMPrinterPort</a>; /** * searchDuration is the time to end search for devices. * default is 15 seconds. *
|
|
292
|
+
<code>{ /** * 'usb' is android only, and now developing. */ port: <a href="#brlmprinterport">BRLMPrinterPort</a>; /** * searchDuration is the time to end search for devices. * default is 15 seconds. * Used for Wi-Fi, BLE, and the iOS Bluetooth accessory picker wait. * Timing out does not dismiss the system accessory picker; close it before retrying. */ searchDuration: number; /** * Android Bluetooth Classic only. Include only devices whose Bluetooth class * reports a printer. Defaults to false; ignored for other ports and on iOS. * This does not identify Brother devices. Devices with an unknown class are excluded when true. */ bluetoothPrintersOnly?: boolean; }</code>
|
|
293
293
|
|
|
294
294
|
|
|
295
295
|
#### isChannelAvailableResult
|
package/dist/docs.json
CHANGED
|
@@ -929,7 +929,7 @@
|
|
|
929
929
|
"docs": "",
|
|
930
930
|
"types": [
|
|
931
931
|
{
|
|
932
|
-
"text": "{\n /**\n * 'usb' is android only, and now developing.\n */\n port: BRLMPrinterPort;\n\n /**\n * searchDuration is the time to end search for devices.\n * default is 15 seconds.\n *
|
|
932
|
+
"text": "{\n /**\n * 'usb' is android only, and now developing.\n */\n port: BRLMPrinterPort;\n\n /**\n * searchDuration is the time to end search for devices.\n * default is 15 seconds.\n * Used for Wi-Fi, BLE, and the iOS Bluetooth accessory picker wait.\n * Timing out does not dismiss the system accessory picker; close it before retrying.\n */\n searchDuration: number;\n /**\n * Android Bluetooth Classic only. Include only devices whose Bluetooth class\n * reports a printer. Defaults to false; ignored for other ports and on iOS.\n * This does not identify Brother devices. Devices with an unknown class are excluded when true.\n */\n bluetoothPrintersOnly?: boolean;\n}",
|
|
933
933
|
"complexTypes": [
|
|
934
934
|
"BRLMPrinterPort"
|
|
935
935
|
]
|
package/dist/esm/interfaces.d.ts
CHANGED
|
@@ -121,7 +121,8 @@ export type BRLMSearchOption = {
|
|
|
121
121
|
/**
|
|
122
122
|
* searchDuration is the time to end search for devices.
|
|
123
123
|
* default is 15 seconds.
|
|
124
|
-
*
|
|
124
|
+
* Used for Wi-Fi, BLE, and the iOS Bluetooth accessory picker wait.
|
|
125
|
+
* Timing out does not dismiss the system accessory picker; close it before retrying.
|
|
125
126
|
*/
|
|
126
127
|
searchDuration: number;
|
|
127
128
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n BRLMPrinterLabelName,\n BRLMPrinterModelName,\n BRLMPrinterAutoCutType,\n BRLMPrinterCompressMode,\n BRLMPrinterHalftone,\n BRLMPrinterHalftoneThresholdType,\n BRLMPrinterHorizontalAlignment,\n BRLMPrinterNumberOfCopies,\n BRLMPrinterPrintQuality,\n BRLMPrinterImageRotation,\n BRLMPrinterScaleMode,\n BRLMPrinterScaleValueType,\n BRLMPrinterVerticalAlignment,\n BRLMPrinterCustomPaperType,\n BRLMPrinterCustomPaperUnit,\n BRLMPrinterPort,\n} from './brother-printer.enum';\n\nexport type BRLMChannelResult = {\n port: BRLMPrinterPort;\n modelName: string;\n serialNumber: string;\n macAddress: string;\n nodeName: string;\n location: string;\n\n /**\n * This need to connect to the printer.\n * wifi: IP Address\n * bluetooth: macAddress\n * bluetoothLowEnergy: modelName for bluetoothLowEnergy\n */\n channelInfo: string;\n};\n\nexport type BRLMPrintOptions = {\n encodedImage: string;\n\n /**\n * Should use enum BRLMPrinterModelName\n */\n modelName: BRLMPrinterModelName;\n} & Partial<BRLMChannelResult> &\n (BRLMPrinterQLModelSettings | BRLMPrinterTDModelSettings);\n\nexport type isChannelAvailableResult = {\n result: boolean;\n};\n\nexport type BRLMPrinterTDModelSettings = {\n /**\n * Should use enum BRKMPrinterCustomPaperType\n */\n paperType: BRLMPrinterCustomPaperType;\n\n /**\n * The width of the label. For example, the RD-U04J1 is 60.0 wide.\n */\n tapeWidth: number;\n\n /**\n * The length of the label. For example, the RD-U04J1 is 60.0 wide.\n */\n tapeLength: number;\n\n /**\n * It is the difference between a sticker and a mount.\n * For example, the RD-U04J1 is `1.0, 2.0, 1.0, 2.0`\n */\n marginTop: number;\n marginRight: number;\n marginBottom: number;\n marginLeft: number;\n\n /**\n * The spacing between seals. For example, the RD-U04J1 is 0.2.\n */\n gapLength: number;\n\n paperMarkPosition: number;\n paperMarkLength: number;\n\n /**\n * Should use enum BRKMPrinterCustomPaperUnit.\n * For example, the RD-U04J1 is mm.\n */\n paperUnit: BRLMPrinterCustomPaperUnit;\n};\n\nexport type BRLMPrinterQLModelSettings = {\n /**\n * Should use enum BRLMPrinterLabelName\n */\n labelName: BRLMPrinterLabelName;\n} & BRLMPrinterSettings;\n\n/**\n * These are optional. If these are not set, default values are assigned by the printer.\n */\nexport type BRLMPrinterSettings = {\n /**\n * The number of copies you print.\n */\n numberOfCopies?: BRLMPrinterNumberOfCopies;\n\n /**\n * Whether the auto-cut is enabled or not. If true, your printer cut the paper each page.\n */\n autoCut?: BRLMPrinterAutoCutType;\n\n /**\n * A scale mode that specifies how your data is scaled in a print area of your printer.\n */\n scaleMode?: BRLMPrinterScaleMode;\n\n /**\n * A scale value. This is effective when ScaleMode is ScaleValue.\n */\n scaleValue?: BRLMPrinterScaleValueType;\n\n /**\n * A way to rasterize your data.\n */\n halftone?: BRLMPrinterHalftone;\n\n /**\n * A threshold value. This is effective when the Halftone is Threshold.\n */\n halftoneThreshold?: BRLMPrinterHalftoneThresholdType;\n\n /**\n * An image rotation that specifies the angle in which your data is placed in the print area. Rotation direction is clockwise.\n */\n imageRotation?: BRLMPrinterImageRotation;\n\n /**\n * A vertical alignment that specifies how your data is placed in the printable area.\n */\n verticalAlignment?: BRLMPrinterVerticalAlignment;\n\n /**\n * A horizontal alignment that specifies how your data is placed in the printable area.\n */\n horizontalAlignment?: BRLMPrinterHorizontalAlignment;\n\n /**\n * A compress mode that specifies how to compress your data.\n * note: This is ios only.\n */\n compressMode?: BRLMPrinterCompressMode;\n\n /**\n * A priority that is print speed or print quality. Whether or not this has an effect is depend on your printer.\n */\n printQuality?: BRLMPrinterPrintQuality;\n};\n\nexport type BRLMSearchOption = {\n /**\n * 'usb' is android only, and now developing.\n */\n port: BRLMPrinterPort;\n\n /**\n * searchDuration is the time to end search for devices.\n * default is 15 seconds.\n *
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n BRLMPrinterLabelName,\n BRLMPrinterModelName,\n BRLMPrinterAutoCutType,\n BRLMPrinterCompressMode,\n BRLMPrinterHalftone,\n BRLMPrinterHalftoneThresholdType,\n BRLMPrinterHorizontalAlignment,\n BRLMPrinterNumberOfCopies,\n BRLMPrinterPrintQuality,\n BRLMPrinterImageRotation,\n BRLMPrinterScaleMode,\n BRLMPrinterScaleValueType,\n BRLMPrinterVerticalAlignment,\n BRLMPrinterCustomPaperType,\n BRLMPrinterCustomPaperUnit,\n BRLMPrinterPort,\n} from './brother-printer.enum';\n\nexport type BRLMChannelResult = {\n port: BRLMPrinterPort;\n modelName: string;\n serialNumber: string;\n macAddress: string;\n nodeName: string;\n location: string;\n\n /**\n * This need to connect to the printer.\n * wifi: IP Address\n * bluetooth: macAddress\n * bluetoothLowEnergy: modelName for bluetoothLowEnergy\n */\n channelInfo: string;\n};\n\nexport type BRLMPrintOptions = {\n encodedImage: string;\n\n /**\n * Should use enum BRLMPrinterModelName\n */\n modelName: BRLMPrinterModelName;\n} & Partial<BRLMChannelResult> &\n (BRLMPrinterQLModelSettings | BRLMPrinterTDModelSettings);\n\nexport type isChannelAvailableResult = {\n result: boolean;\n};\n\nexport type BRLMPrinterTDModelSettings = {\n /**\n * Should use enum BRKMPrinterCustomPaperType\n */\n paperType: BRLMPrinterCustomPaperType;\n\n /**\n * The width of the label. For example, the RD-U04J1 is 60.0 wide.\n */\n tapeWidth: number;\n\n /**\n * The length of the label. For example, the RD-U04J1 is 60.0 wide.\n */\n tapeLength: number;\n\n /**\n * It is the difference between a sticker and a mount.\n * For example, the RD-U04J1 is `1.0, 2.0, 1.0, 2.0`\n */\n marginTop: number;\n marginRight: number;\n marginBottom: number;\n marginLeft: number;\n\n /**\n * The spacing between seals. For example, the RD-U04J1 is 0.2.\n */\n gapLength: number;\n\n paperMarkPosition: number;\n paperMarkLength: number;\n\n /**\n * Should use enum BRKMPrinterCustomPaperUnit.\n * For example, the RD-U04J1 is mm.\n */\n paperUnit: BRLMPrinterCustomPaperUnit;\n};\n\nexport type BRLMPrinterQLModelSettings = {\n /**\n * Should use enum BRLMPrinterLabelName\n */\n labelName: BRLMPrinterLabelName;\n} & BRLMPrinterSettings;\n\n/**\n * These are optional. If these are not set, default values are assigned by the printer.\n */\nexport type BRLMPrinterSettings = {\n /**\n * The number of copies you print.\n */\n numberOfCopies?: BRLMPrinterNumberOfCopies;\n\n /**\n * Whether the auto-cut is enabled or not. If true, your printer cut the paper each page.\n */\n autoCut?: BRLMPrinterAutoCutType;\n\n /**\n * A scale mode that specifies how your data is scaled in a print area of your printer.\n */\n scaleMode?: BRLMPrinterScaleMode;\n\n /**\n * A scale value. This is effective when ScaleMode is ScaleValue.\n */\n scaleValue?: BRLMPrinterScaleValueType;\n\n /**\n * A way to rasterize your data.\n */\n halftone?: BRLMPrinterHalftone;\n\n /**\n * A threshold value. This is effective when the Halftone is Threshold.\n */\n halftoneThreshold?: BRLMPrinterHalftoneThresholdType;\n\n /**\n * An image rotation that specifies the angle in which your data is placed in the print area. Rotation direction is clockwise.\n */\n imageRotation?: BRLMPrinterImageRotation;\n\n /**\n * A vertical alignment that specifies how your data is placed in the printable area.\n */\n verticalAlignment?: BRLMPrinterVerticalAlignment;\n\n /**\n * A horizontal alignment that specifies how your data is placed in the printable area.\n */\n horizontalAlignment?: BRLMPrinterHorizontalAlignment;\n\n /**\n * A compress mode that specifies how to compress your data.\n * note: This is ios only.\n */\n compressMode?: BRLMPrinterCompressMode;\n\n /**\n * A priority that is print speed or print quality. Whether or not this has an effect is depend on your printer.\n */\n printQuality?: BRLMPrinterPrintQuality;\n};\n\nexport type BRLMSearchOption = {\n /**\n * 'usb' is android only, and now developing.\n */\n port: BRLMPrinterPort;\n\n /**\n * searchDuration is the time to end search for devices.\n * default is 15 seconds.\n * Used for Wi-Fi, BLE, and the iOS Bluetooth accessory picker wait.\n * Timing out does not dismiss the system accessory picker; close it before retrying.\n */\n searchDuration: number;\n /**\n * Android Bluetooth Classic only. Include only devices whose Bluetooth class\n * reports a printer. Defaults to false; ignored for other ports and on iOS.\n * This does not identify Brother devices. Devices with an unknown class are excluded when true.\n */\n bluetoothPrintersOnly?: boolean;\n};\n\nexport type ErrorInfo = {\n message: string;\n code: number;\n};\n"]}
|
package/docs/search.md
CHANGED
|
@@ -47,13 +47,15 @@ const stopSearching = async () => {
|
|
|
47
47
|
|
|
48
48
|
Call `searchWifiPrinters` from the search button and await `stopSearching` when leaving the screen.
|
|
49
49
|
|
|
50
|
-
On iOS, `bluetooth` first lists connected MFi printers. If none are connected, the app displays the system Bluetooth accessory picker so you can select and pair a printer. The search promise completes after the picker callback; picker errors reject the promise.
|
|
50
|
+
On iOS, `bluetooth` first lists connected MFi printers. If none are connected, the app displays the system Bluetooth accessory picker so you can select and pair a printer. The search promise completes after the picker callback; picker errors reject the promise. The picker wait rejects after `searchDuration` seconds (default 15, minimum 1), or when `cancelSearchBluetoothPrinter()` is called. Late picker results are ignored. Apple does not provide an API to dismiss this picker: close it before retrying. While the old picker remains open, another picker request rejects immediately. If the system never displays or closes it, restart the app before retrying.
|
|
51
|
+
|
|
52
|
+
When migrating to `SceneDelegate`, including during the Capacitor 8.5 update, also assign the scene window to `AppDelegate.window`, which the system accessory picker uses. After creating the scene window, set `(UIApplication.shared.delegate as? AppDelegate)?.window = window`. Without this reference, the picker may not appear even though the search has started.
|
|
51
53
|
|
|
52
54
|
For BLE-capable printers, use `port: BRLMPrinterPort.bluetoothLowEnergy`. On iOS this uses `startBLESearch`, without the Bluetooth accessory picker. Pass the discovered printer's `channelInfo` (BLE local name) unchanged to `isChannelAvailable` or `printImage`. BLE search errors reject the search promise. QL-820NWB/QL-820NWBc do not support BLE printing; use `bluetooth` or `wifi` for these models.
|
|
53
55
|
|
|
54
56
|
On Android, pair a Bluetooth printer in the system settings before calling `search` with `bluetooth`; the SDK lists paired printers and does not provide the iOS accessory picker. Bluetooth and BLE searches resolve after the search finishes, or reject on SDK errors. Android 12 and later request Nearby devices permissions; Android 11 and earlier request location permission for BLE. `isChannelAvailable` returns `false` when Bluetooth permission is missing.
|
|
55
57
|
|
|
56
|
-
`searchDuration` applies to `wifi` and `
|
|
58
|
+
`searchDuration` applies to `wifi`, `bluetoothLowEnergy`, and the iOS `bluetooth` accessory-picker wait. `usb` is Android only. Completed Wi-Fi/BLE searches with no results resolve without printers; iOS accessory-picker errors, cancellation, and wait timeouts reject the search. Cancellation also rejects an in-progress iOS Bluetooth initial scan and prevents its late result from opening the picker. Signatures are on the [API](/docs/api#brlmsearchoption) page.
|
|
57
59
|
|
|
58
60
|
On Android, Bluetooth Classic searches return paired devices. To include only devices that report the Bluetooth Imaging/Printer class:
|
|
59
61
|
|
|
@@ -19,6 +19,8 @@ public class BrotherPrintPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
19
19
|
]
|
|
20
20
|
private var cancelRoutineWiFi: (() -> Void)?
|
|
21
21
|
private var cancelRoutineBluetooth: (() -> Void)?
|
|
22
|
+
private var bluetoothAccessoryPickerActive = false
|
|
23
|
+
private var cancelAccessorySearch: (() -> Void)?
|
|
22
24
|
|
|
23
25
|
@objc func printImage(_ call: CAPPluginCall) {
|
|
24
26
|
let encodedImage: String = call.getString("encodedImage", "")
|
|
@@ -201,35 +203,85 @@ public class BrotherPrintPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
201
203
|
}
|
|
202
204
|
}
|
|
203
205
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
func checkBLEChannel(
|
|
207
|
+
_ call: CAPPluginCall,
|
|
208
|
+
scan: @escaping () -> (channels: [BRLMChannel], error: BRLMPrinterSearchErrorCode) = {
|
|
209
|
+
let result = BRLMPrinterSearcher.startBluetoothSearch()
|
|
210
|
+
return (result.channels, result.error.code)
|
|
211
|
+
},
|
|
212
|
+
startAccessorySearch: @escaping (@escaping (BRLMPrinterSearchResult) -> Void) -> Void = BRLMPrinterSearcher.startBluetoothAccessorySearch
|
|
213
|
+
) {
|
|
214
|
+
DispatchQueue.main.async {
|
|
215
|
+
var cancelled = false
|
|
216
|
+
self.cancelAccessorySearch = {
|
|
217
|
+
cancelled = true
|
|
218
|
+
self.cancelAccessorySearch = nil
|
|
219
|
+
call.reject("Bluetooth accessory search cancelled.")
|
|
210
220
|
}
|
|
211
|
-
|
|
221
|
+
DispatchQueue.global().async {
|
|
222
|
+
let result = scan()
|
|
212
223
|
DispatchQueue.main.async {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
for channel in result.channels {
|
|
219
|
-
self.notifyListeners(BrotherPrinterEvent.onPrinterAvailable.rawValue, data: self.chanelToPrinter(port: "bluetooth", channel: channel))
|
|
220
|
-
}
|
|
221
|
-
call.resolve()
|
|
224
|
+
guard !cancelled else { return }
|
|
225
|
+
self.cancelAccessorySearch = nil
|
|
226
|
+
guard result.error == .noError else {
|
|
227
|
+
call.reject("Error - startBluetoothSearch: " + PrinterSearchErrorModel.fetchChannelErrorCode(error: result.error))
|
|
228
|
+
return
|
|
222
229
|
}
|
|
230
|
+
if result.channels.isEmpty {
|
|
231
|
+
self.searchBluetoothAccessory(call, startSearch: startAccessorySearch)
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
for channel in result.channels {
|
|
235
|
+
self.notifyListeners(BrotherPrinterEvent.onPrinterAvailable.rawValue, data: self.chanelToPrinter(port: "bluetooth", channel: channel))
|
|
236
|
+
}
|
|
237
|
+
call.resolve()
|
|
223
238
|
}
|
|
224
|
-
return
|
|
225
239
|
}
|
|
226
|
-
for channel in searcher.channels {
|
|
227
|
-
NSLog(channel.channelInfo)
|
|
228
|
-
self.notifyListeners(BrotherPrinterEvent.onPrinterAvailable.rawValue, data: self.chanelToPrinter(port: "bluetooth", channel: channel))
|
|
229
|
-
}
|
|
230
|
-
call.resolve()
|
|
231
240
|
}
|
|
241
|
+
}
|
|
232
242
|
|
|
243
|
+
func searchBluetoothAccessory(
|
|
244
|
+
_ call: CAPPluginCall,
|
|
245
|
+
startSearch: (@escaping (BRLMPrinterSearchResult) -> Void) -> Void = BRLMPrinterSearcher.startBluetoothAccessorySearch
|
|
246
|
+
) {
|
|
247
|
+
guard !self.bluetoothAccessoryPickerActive else {
|
|
248
|
+
call.reject("Bluetooth accessory picker is still open. Close it before searching again.")
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
self.bluetoothAccessoryPickerActive = true
|
|
252
|
+
// Only the OS callback closes the picker; timeout/cancellation ends our wait, not the system UI.
|
|
253
|
+
var finished = false
|
|
254
|
+
let finish = { () -> Bool in
|
|
255
|
+
guard !finished else { return false }
|
|
256
|
+
finished = true
|
|
257
|
+
self.cancelAccessorySearch = nil
|
|
258
|
+
return true
|
|
259
|
+
}
|
|
260
|
+
let timeout = DispatchWorkItem {
|
|
261
|
+
guard finish() else { return }
|
|
262
|
+
call.reject("Bluetooth accessory search timed out. Close the accessory picker before retrying.")
|
|
263
|
+
}
|
|
264
|
+
self.cancelAccessorySearch = {
|
|
265
|
+
guard finish() else { return }
|
|
266
|
+
timeout.cancel()
|
|
267
|
+
call.reject("Bluetooth accessory search cancelled.")
|
|
268
|
+
}
|
|
269
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + Double(max(1, call.getInt("searchDuration", 15))), execute: timeout)
|
|
270
|
+
startSearch { result in
|
|
271
|
+
DispatchQueue.main.async {
|
|
272
|
+
self.bluetoothAccessoryPickerActive = false
|
|
273
|
+
guard finish() else { return }
|
|
274
|
+
timeout.cancel()
|
|
275
|
+
guard result.error.code == BRLMPrinterSearchErrorCode.noError else {
|
|
276
|
+
call.reject("Error - startBluetoothAccessorySearch: " + PrinterSearchErrorModel.fetchChannelErrorCode(error: result.error.code))
|
|
277
|
+
return
|
|
278
|
+
}
|
|
279
|
+
for channel in result.channels {
|
|
280
|
+
self.notifyListeners(BrotherPrinterEvent.onPrinterAvailable.rawValue, data: self.chanelToPrinter(port: "bluetooth", channel: channel))
|
|
281
|
+
}
|
|
282
|
+
call.resolve()
|
|
283
|
+
}
|
|
284
|
+
}
|
|
233
285
|
}
|
|
234
286
|
|
|
235
287
|
private func searchBLEPrinter(_ call: CAPPluginCall) {
|
|
@@ -280,10 +332,13 @@ public class BrotherPrintPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
280
332
|
}
|
|
281
333
|
|
|
282
334
|
@objc func cancelSearchBluetoothPrinter(_ call: CAPPluginCall) {
|
|
283
|
-
DispatchQueue.
|
|
284
|
-
self.
|
|
285
|
-
|
|
286
|
-
|
|
335
|
+
DispatchQueue.main.async {
|
|
336
|
+
self.cancelAccessorySearch?()
|
|
337
|
+
DispatchQueue.global().async {
|
|
338
|
+
self.cancelRoutineBluetooth?()
|
|
339
|
+
self.cancelRoutineBluetooth = nil
|
|
340
|
+
call.resolve()
|
|
341
|
+
}
|
|
287
342
|
}
|
|
288
343
|
}
|
|
289
344
|
}
|
|
@@ -2,6 +2,89 @@ import XCTest
|
|
|
2
2
|
import Capacitor
|
|
3
3
|
@testable import BrotherPrintPlugin
|
|
4
4
|
|
|
5
|
+
class BluetoothAccessorySearchTests: XCTestCase {
|
|
6
|
+
func testCancellationDuringInitialScanDoesNotOpenPicker() {
|
|
7
|
+
let scanStarted = expectation(description: "Initial scan started")
|
|
8
|
+
let scanFinished = expectation(description: "Initial scan returned")
|
|
9
|
+
let pickerOpened = expectation(description: "Cancelled scan must not open picker")
|
|
10
|
+
pickerOpened.isInverted = true
|
|
11
|
+
let releaseScan = DispatchSemaphore(value: 0)
|
|
12
|
+
let plugin = BrotherPrintPlugin()
|
|
13
|
+
var rejections = 0
|
|
14
|
+
let call = CAPPluginCall(callbackId: "initial-scan", methodName: "search", options: [:], success: { _, _ in
|
|
15
|
+
XCTFail("Cancelled search must not resolve")
|
|
16
|
+
}, error: { error in
|
|
17
|
+
rejections += 1
|
|
18
|
+
XCTAssertTrue(error?.message.contains("cancelled") == true)
|
|
19
|
+
})!
|
|
20
|
+
plugin.checkBLEChannel(call, scan: {
|
|
21
|
+
scanStarted.fulfill()
|
|
22
|
+
XCTAssertEqual(releaseScan.wait(timeout: .now() + 3), .success)
|
|
23
|
+
scanFinished.fulfill()
|
|
24
|
+
return ([], .noError)
|
|
25
|
+
}, startAccessorySearch: { _ in
|
|
26
|
+
pickerOpened.fulfill()
|
|
27
|
+
})
|
|
28
|
+
wait(for: [scanStarted], timeout: 3)
|
|
29
|
+
let cancel = CAPPluginCall(callbackId: "stop", methodName: "cancelSearchBluetoothPrinter", options: [:], success: { _, _ in
|
|
30
|
+
releaseScan.signal()
|
|
31
|
+
}, error: { _ in
|
|
32
|
+
XCTFail("Cancellation must resolve")
|
|
33
|
+
})!
|
|
34
|
+
plugin.cancelSearchBluetoothPrinter(cancel)
|
|
35
|
+
wait(for: [scanFinished], timeout: 3)
|
|
36
|
+
wait(for: [pickerOpened], timeout: 0.2)
|
|
37
|
+
XCTAssertEqual(rejections, 1)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func testMissingPickerCallbackTimesOutAndDoesNotOpenAnotherPicker() {
|
|
41
|
+
let timedOut = expectation(description: "Search rejects without a picker callback")
|
|
42
|
+
let plugin = BrotherPrintPlugin()
|
|
43
|
+
var starts = 0
|
|
44
|
+
let call = CAPPluginCall(callbackId: "timeout", methodName: "search", options: ["searchDuration": 1], success: { _, _ in
|
|
45
|
+
XCTFail("Search must reject")
|
|
46
|
+
}, error: { error in
|
|
47
|
+
XCTAssertTrue(error?.message.contains("timed out") == true)
|
|
48
|
+
let retry = CAPPluginCall(callbackId: "retry", methodName: "search", options: [:], success: { _, _ in
|
|
49
|
+
XCTFail("A second picker must not open")
|
|
50
|
+
}, error: { error in
|
|
51
|
+
XCTAssertTrue(error?.message.contains("still open") == true)
|
|
52
|
+
})!
|
|
53
|
+
plugin.searchBluetoothAccessory(retry) { _ in starts += 1 }
|
|
54
|
+
XCTAssertEqual(starts, 1)
|
|
55
|
+
timedOut.fulfill()
|
|
56
|
+
})!
|
|
57
|
+
DispatchQueue.main.async {
|
|
58
|
+
plugin.searchBluetoothAccessory(call) { _ in starts += 1 }
|
|
59
|
+
}
|
|
60
|
+
wait(for: [timedOut], timeout: 3)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func testCancellationRejectsOnlyOnceEvenAfterDeadline() {
|
|
64
|
+
let finished = expectation(description: "Cancellation stays settled after the deadline")
|
|
65
|
+
let plugin = BrotherPrintPlugin()
|
|
66
|
+
var rejections = 0
|
|
67
|
+
let call = CAPPluginCall(callbackId: "cancel", methodName: "search", options: ["searchDuration": 1], success: { _, _ in
|
|
68
|
+
XCTFail("Search must reject")
|
|
69
|
+
}, error: { error in
|
|
70
|
+
rejections += 1
|
|
71
|
+
XCTAssertTrue(error?.message.contains("cancelled") == true)
|
|
72
|
+
})!
|
|
73
|
+
let cancel = CAPPluginCall(callbackId: "stop", methodName: "cancelSearchBluetoothPrinter", options: [:], success: { _, _ in }, error: { _ in
|
|
74
|
+
XCTFail("Cancellation must resolve")
|
|
75
|
+
})!
|
|
76
|
+
DispatchQueue.main.async {
|
|
77
|
+
plugin.searchBluetoothAccessory(call) { _ in }
|
|
78
|
+
plugin.cancelSearchBluetoothPrinter(cancel)
|
|
79
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
|
|
80
|
+
XCTAssertEqual(rejections, 1)
|
|
81
|
+
finished.fulfill()
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
wait(for: [finished], timeout: 3)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
5
88
|
class PrintImageValidationTests: XCTestCase {
|
|
6
89
|
func testInvalidImagesRejectBeforeOpeningPrinter() {
|
|
7
90
|
for image in ["", "A", "SGVsbG8=", "iVBORw0KGgo="] {
|