Skip to content

Commit 78be2df

Browse files
authored
Merge pull request #93 from NordicSemiconductor/documentation
Documentation improvements
2 parents 43204e2 + 763772c commit 78be2df

File tree

414 files changed

+671
-584
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

414 files changed

+671
-584
lines changed

CoreBluetoothMock/Documentation.docc/CoreBluetoothMock.md

Lines changed: 9 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -13,197 +13,23 @@ Bluetooth LE devices using an implementation in Swift. This allows:
1313
> Note: Current version supports testing only central manager features.
1414
The peripheral manager functionality is planned.
1515

16-
## Migration
17-
18-
To make migration from **CoreBluetooth** to **CoreBluetoothMock** easy the API of the
19-
library was designed to similar to the native one. Only a few changes are required,
20-
most of them involve changing or removing the `import CoreBluetooth` statement, not the
21-
application code.
22-
23-
The migration can be done in one of 2 ways:
24-
25-
#### Using aliases (recommended)
26-
27-
1. Copy `CoreBluetoothTypeAliases.swift` file from the *Example app* to your project.
28-
This file contains number of type aliases for all `CBM...` types and renames them to `CB...`,
29-
therfore removing the not need to perform any changes in your code.
30-
2. Remove:
31-
```swift
32-
import CoreBluetooth
33-
```
34-
in all your files, as the types are now defined locally in the project.
35-
36-
#### Direct
37-
38-
1. In all files using **CoreBluetooth** replace
39-
```swift
40-
import CoreBluetooth
41-
```
42-
with
43-
```swift
44-
import CoreBluetoothMock
45-
```
46-
2. Replace all instances of `CB...` with `CBM...`.
47-
48-
### Initialization
49-
50-
Due to the fact, that the library provides two different implementations of ``CBMCentralManager``
51-
there is a difference, comparing to the native API, how the manager is initialized. Instead of:
52-
```swift
53-
let manager = CBCentralManager(delegate: self, queue: ..., options: ...)
54-
```
55-
you need to use the ``CBMCentralManagerFactory``:
56-
```swift
57-
let manager = CBMCentralManagerFactory.initiate(delegate: self, queue: ..., options: ..., forceMock: ...)
58-
```
59-
The last parameter, `forceMock`, when set to `true`, allows to run the mock implementation
60-
also on a physical device.
61-
62-
## Mocking Bluetooth LE Devices
63-
64-
The ``CBMCentralManagerFactory`` provides two implementatons of ``CBMCentralManager``:
65-
* ``CBMCentralManagerNative``
66-
* ``CBMCentralManagerMock``
67-
68-
The native implementation proxies all requests to the **CoreBluetooth** framework.
69-
70-
When the code runs on a simulator (or the `forceMock` parameter was set) a mock manager
71-
is created. Instead of physical devices, this manager interacts with mock implementations,
72-
defined as ``CBMPeripheralSpec``. Such peripheral specification should emulate the actual
73-
behavior of a real device as close as possible.
74-
75-
### Defining a Mock Peripheral
76-
77-
To create a mock peripheral use
78-
``CBMPeripheralSpec/simulatePeripheral(identifier:proximity:)``. This method returns a
79-
``CBMPeripheralSpec/Builder`` instance which can set up advertisements and connection behavior.
80-
Any number of such specifications can be defined.
81-
82-
Sample code:
83-
```swift
84-
let blinky = CBMPeripheralSpec
85-
.simulatePeripheral(proximity: .near)
86-
.advertising(
87-
advertisementData: [
88-
CBMAdvertisementDataLocalNameKey : "nRF Blinky",
89-
CBMAdvertisementDataServiceUUIDsKey : [CBMUUID.nordicBlinkyService],
90-
CBMAdvertisementDataIsConnectable : true as NSNumber
91-
],
92-
withInterval: 0.250)
93-
.connectable(
94-
name: "nRF Blinky",
95-
services: [.blinkyService],
96-
delegate: BlinkyCBMPeripheralSpecDelegate(),
97-
connectionInterval: 0.045,
98-
mtu: 23)
99-
.build()
100-
```
101-
102-
Such mock peripherals must be added to the simulation using
103-
``CBMCentralManagerMock/simulatePeripherals(_:)``.
104-
105-
```swift
106-
CBMCentralManagerMock.simulatePeripherals([blinky])
107-
```
108-
109-
From that moment simulated advertising starts and the device can be scanned or retrieved
110-
just like physical devices.
111-
112-
### Advertising
113-
114-
A mock peripheral may advertise with:
115-
* static data with a fixed advertising interval,
116-
* *one-time* advertisements (`interval` set to 0),
117-
118-
Both types of advertisements can be delayed using the `delay` parameter.
119-
120-
The initial advertising configuration is set up using
121-
``CBMPeripheralSpec/Builder/advertising(advertisementData:withInterval:delay:alsoWhenConnected:)``,
122-
which can be called multiple times, if required.
123-
124-
The advertisement data can be changed during the simulation using
125-
``CBMPeripheralSpec/simulateAdvertisementChange(_:)``.
126-
127-
### Connection
128-
129-
The
130-
``CBMPeripheralSpec/Builder/connectable(name:services:delegate:connectionInterval:mtu:)`` or
131-
``CBMPeripheralSpec/Builder/connected(name:services:delegate:connectionInterval:mtu:)``
132-
methods allows to specify a ``CBMPeripheralSpecDelegate``. This object defines the behavior of the
133-
mock peripheral, how will it respond to Bluetooth LE requests, a hard reset, etc. The implementation
134-
should mimic the behavoir of the real device as much as possible to make the tests reliable.
135-
136-
To test how the app handles connection interruptions, the mock connection can be terminated using
137-
``CBMPeripheralSpec/simulateReset()``, ``CBMPeripheralSpec/simulateDisconnection(withError:)`` or
138-
``CBMPeripheralSpec/simulateProximityChange(_:)`` with parameter ``CBMProximity/outOfRange``.
139-
140-
## Simulation
141-
142-
``CBMPeripheralSpec/simulateConnection()`` - simulates a situation when another app on the iDevice
143-
connected to this peripheral. The device will stop advertising (unless `advertisingWhenConnected`
144-
flag was set) and will be available using
145-
``CBMCentralManager/retrieveConnectedPeripherals(withServices:)``.
146-
147-
``CBMPeripheralSpec/simulateDisconnection(withError:)`` - simulates a connection error.
148-
149-
``CBMPeripheralSpec/simulateReset()`` - simulates device hard reset. The central will notify
150-
delegates 4 seconds (supervision timeout) after the device has been reset.
151-
152-
``CBMPeripheralSpec/simulateProximityChange(_:)`` - simulates moving the peripheral close or away
153-
from the device.
154-
155-
``CBMPeripheralSpec/simulateValueUpdate(_:for:)`` - simulates sending a notification or indication
156-
from the device. All subscribed clients will be notified a connection interval later.
157-
158-
``CBMPeripheralSpec/simulateAdvertisementChange(_:)`` - simulates change of the advertisemet data
159-
of the peripheral. The peripheral will stop advertising with previous data and start with the new set.
160-
161-
``CBMPeripheralSpec/simulateCaching()`` - simulates caching the device by the iDevice.
162-
Caching pairs the device's MAC with a random identifier (UUID). A device is also cached whenever
163-
it is scanned. Caching makes the device available to be retrieved using
164-
``CBMCentralManager/retrievePeripherals(withIdentifiers:)``.
165-
166-
``CBMPeripheralSpec/simulateMacChange(_:)`` - simulates the device changing its MAC address.
167-
The iDevice will not contain any cached information about the device, as with the new MAC it is
168-
considered to be a new device.
169-
170-
171-
### Bluetooth State Changes
172-
173-
``CBMCentralManagerMock/simulatePeripherals(_:)`` - creates a simulation with given list of mock
174-
peripheral. This method should be called when the manager is powered off, or before any
175-
central manager was initialized.
176-
177-
``CBMCentralManagerMock/simulateInitialState(_:)`` - this method should be called before any central
178-
manager instance was created. It defines the initial state of the mock central manager.
179-
By default, the manager is powered off.
180-
181-
``CBMCentralManagerMock/simulatePowerOn()`` - turns on the mock central manager.
16+
## Topics
18217

183-
``CBMCentralManagerMock/simulatePowerOff()`` - turns off the mock central manager.
184-
All scans and connections will be terminated.
18+
### How to migrate a project to CoreBluetooth Mock framework
18519

186-
``CBMCentralManagerMock/tearDownSimulation()`` - sets the state of all currently existing central
187-
managers to ``CBMManagerState/unknown`` and clears the list of managers and peripherals bringing
188-
the mock manager to initial state.
20+
- <doc:Migration-guide>
18921

190-
``CBMCentralManagerMock/simulateStateRestoration`` - this closure will be used when you initiate a
191-
central manager with ``CBMCentralManagerOptionRestoreIdentifierKey`` option. The map returned will be
192-
passed to ``CBMCentralManagerDelegate/centralManager(_:willRestoreState:)-9qavl`` callback in
193-
central manager's delegate.
22+
### How to create mock peripherals
19423

195-
``CBMCentralManagerMock/simulateFeaturesSupport`` - this closure will be used to emulate Bluetooth
196-
features supported by the manager. It is available on iOS 13+, tvOS 13+ or watchOS 6+.
24+
- <doc:Mocking-peripherals>
19725

198-
``CBMCentralManagerMock/simulateAuthorization(_:)`` - simulates the current authorization state
199-
of a Core Bluetooth manager. When any value other than `.allowedAlways` is returned, the
200-
``CBMCentralManager`` will change state to ``CBMManagerState/unauthorized``.
26+
### How to simulate test events
20127

202-
## Known limitations
28+
- <doc:Simulation>
20329

204-
As ``CBMPeripheral`` is a *protocol*, the KVO features are not available. See [#10](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock/issues/10).
30+
### Known issues
20531

206-
## Topics
32+
- <doc:Known-issues>
20733

20834
### Mocking Bluetooth LE Devices
20935

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Known issues
2+
3+
Known issues when using **CoreBluetoothMock** framework instead of native **CoreBluetooth**.
4+
5+
## Overview
6+
7+
By design, the library should behave exatly the same as the native implementation and no
8+
code changes above those mentioned in <doc:Migration-guide> should be necessary.
9+
10+
However, to make mocking possible, some tradeoffs were made.
11+
12+
### Differences vs native API
13+
14+
1. As ``CBMPeripheral`` is a *protocol*, the KVO features are not available.
15+
See [#10](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock/issues/10).
16+
17+
### Not implemented
18+
19+
1. As of now, the `CBPeripheralManager` is not supported.
20+
See [#40](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock/issues/40).
21+
2. Bluetooth authorization popups are not implemented.
22+
See [#64](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock/issues/64).
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Migration guide
2+
3+
Migration guide from **CoreBluetooth** to **CoreBluetoothFramework**.
4+
5+
## Overview
6+
7+
The API of the library was designed to similar to the native one to make migration
8+
from **CoreBluetooth** to **CoreBluetoothMock** easy. Only few changes are required.
9+
Those include initialization of ``CBMCentralManager`` and fixing possible issue with comparing
10+
``CBMPeripheral`` objects.
11+
12+
### Adding dependency
13+
14+
Add dependency to **CoreBluetoothMock** framework using one of the following:
15+
* [Swift Package Manager](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock#swift-package-manager),
16+
* [CocoaPods](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock#cocoapods)
17+
* [Carthage](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock#carthage).
18+
19+
With this step complete, the migration can be done in one of 2 ways:
20+
21+
#### Using aliases (recommended)
22+
23+
1. Copy [`CoreBluetoothTypeAliases.swift`](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock/blob/main/Example/nRFBlinky/CoreBluetoothTypeAliases.swift)
24+
file from the *Example app* to your project.
25+
This file contains number of type aliases for all `CBM...` types and renames them to `CB...`,
26+
therfore removing the not need to perform any changes in your code.
27+
2. Optionally, remove:
28+
```swift
29+
import CoreBluetooth
30+
```
31+
in all your files, as the types are now defined locally in the project. This step is not required,
32+
as locally defined types take precedense over frameworks.
33+
34+
#### Direct
35+
36+
1. In all files using **CoreBluetooth** replace
37+
```swift
38+
import CoreBluetooth
39+
```
40+
with
41+
```swift
42+
import CoreBluetoothMock
43+
```
44+
2. Replace all instances of `CB...` with `CBM...`.
45+
46+
### Fixing compilation issues
47+
48+
Whichever approach you have chosen, the project now contain compilation errors.
49+
50+
1. To create an instance of a ``CBMCentralManager`` use
51+
``CBMCentralManagerFactory/instance(delegate:queue:forceMock:)`` instead of creating
52+
the manager using an initializer. The last parameter, `forceMock`, when set to `true`,
53+
allows to run the mock implementation also on a physical device.
54+
55+
Before:
56+
```swift
57+
let centralManager = CBCentralManager(delegate: self, queue: .main)
58+
```
59+
After:
60+
```swift
61+
let centralManager = CBCentralManagerFactory.instance(delegate: self,
62+
queue: .main,
63+
forceMock: false)
64+
```
65+
2. If you're comparing ``CBMPeripheral`` instances using == operator, replace it with
66+
comparing their identifiers.
67+
68+
Before:
69+
```swift
70+
peripheral == otherPeripheral
71+
```
72+
After:
73+
```swift
74+
peripheral.identifier == otherPeripheral.identifier
75+
```
76+
77+
## Migration Example
78+
79+
Check out [Migration example](https://github.com/NordicSemiconductor/IOS-CoreBluetooth-Mock-Example) application for step-by-step guide.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Mocking Bluetooth LE Devices
2+
3+
How to create mock peripherals to be used in tests.
4+
5+
## Overview
6+
7+
The ``CBMCentralManagerFactory`` provides two implementatons of ``CBMCentralManager``:
8+
* ``CBMCentralManagerNative``
9+
* ``CBMCentralManagerMock``
10+
11+
The native implementation proxies all requests to the **CoreBluetooth** framework.
12+
13+
When the code runs on a simulator (or the `forceMock` parameter was set) a mock manager
14+
is created. Instead of physical devices, this manager interacts with mock implementations,
15+
defined as ``CBMPeripheralSpec``. Such peripheral specification should emulate the actual
16+
behavior of a real device as close as possible.
17+
18+
### Defining a Mock Peripheral
19+
20+
To create a mock peripheral use
21+
``CBMPeripheralSpec/simulatePeripheral(identifier:proximity:)``. This method returns a
22+
``CBMPeripheralSpec/Builder`` instance which can set up advertisements and connection behavior.
23+
Any number of such specifications can be defined.
24+
25+
Sample code:
26+
```swift
27+
let blinky = CBMPeripheralSpec
28+
.simulatePeripheral(proximity: .near)
29+
.advertising(
30+
advertisementData: [
31+
CBMAdvertisementDataLocalNameKey : "nRF Blinky",
32+
CBMAdvertisementDataServiceUUIDsKey : [CBMUUID.nordicBlinkyService],
33+
CBMAdvertisementDataIsConnectable : true as NSNumber
34+
],
35+
withInterval: 0.250)
36+
.connectable(
37+
name: "nRF Blinky",
38+
services: [.blinkyService],
39+
delegate: BlinkyCBMPeripheralSpecDelegate(),
40+
connectionInterval: 0.045,
41+
mtu: 23)
42+
.build()
43+
```
44+
45+
Such mock peripherals must be added to the simulation using
46+
``CBMCentralManagerMock/simulatePeripherals(_:)``.
47+
48+
```swift
49+
CBMCentralManagerMock.simulatePeripherals([blinky])
50+
```
51+
52+
From that moment simulated advertising starts and the device can be scanned or retrieved
53+
just like physical devices.
54+
55+
### Advertising
56+
57+
A mock peripheral may advertise with:
58+
* static data with a fixed advertising interval,
59+
* *one-time* advertisements (`interval` set to 0),
60+
61+
Both types of advertisements can be delayed using the `delay` parameter.
62+
63+
The initial advertising configuration is set up using
64+
``CBMPeripheralSpec/Builder/advertising(advertisementData:withInterval:delay:alsoWhenConnected:)``,
65+
which can be called multiple times, if required.
66+
67+
The advertisement data can be changed during the simulation using
68+
``CBMPeripheralSpec/simulateAdvertisementChange(_:)``.
69+
70+
### Connection
71+
72+
The
73+
``CBMPeripheralSpec/Builder/connectable(name:services:delegate:connectionInterval:mtu:)`` or
74+
``CBMPeripheralSpec/Builder/connected(name:services:delegate:connectionInterval:mtu:)``
75+
methods allows to specify a ``CBMPeripheralSpecDelegate``. This object defines the behavior of the
76+
mock peripheral, how will it respond to Bluetooth LE requests, a hard reset, etc. The implementation
77+
should mimic the behavoir of the real device as much as possible to make the tests reliable.
78+
79+
To test how the app handles connection interruptions, the mock connection can be terminated using
80+
``CBMPeripheralSpec/simulateReset()``, ``CBMPeripheralSpec/simulateDisconnection(withError:)`` or
81+
``CBMPeripheralSpec/simulateProximityChange(_:)`` with parameter ``CBMProximity/outOfRange``.

0 commit comments

Comments
 (0)