Skip to content

Commit

Permalink
refactor(plugin): add filters to listeners to improve flexibility
Browse files Browse the repository at this point in the history
  • Loading branch information
matey97 committed Jul 21, 2022
1 parent cfcd8bf commit 42ec2a4
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 264 deletions.
157 changes: 0 additions & 157 deletions demo/app/tests/internal/sensor-callback-manager.spec.ts

This file was deleted.

143 changes: 143 additions & 0 deletions demo/app/tests/internal/sensor-listener-manager.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { ListenerFilter, SensorListenerManager } from "nativescript-wearos-sensors/internal/sensor-listener-manager";
import { SensorRecord } from "nativescript-wearos-sensors/internal/sensors/sensor-record";
import { buildFakeSensorRecords } from "~/tests/internal/index.spec";
import { SensorType } from "nativescript-wearos-sensors/internal/sensors/sensor-type";
import { SensorSample } from "nativescript-wearos-sensors/internal/sensors/sample";
import { Node } from "nativescript-wearos-sensors/internal/node";

describe("Sensor listener manager", () => {
const nodeA = new Node("testNodeA", "testNodeA");
const nodeB = new Node("testNodeB", "testNodeB");
const accelerometerType = SensorType.ACCELEROMETER;
const locationType = SensorType.LOCATION;

const sensorRecord1: SensorSample = {
timestamp: Date.now()
};
const sensorRecord2: SensorSample = {
timestamp: Date.now()
};

let listenerManager: SensorListenerManager;

beforeEach(() => {
listenerManager = new SensorListenerManager();
})

it("adds a listener and return its id", () => {
const listener = (_) => null;
const listenerId = listenerManager.add(listener, {});
expect(listenerId).toBeGreaterThanOrEqual(0);
});

it("notifies the listeners registered for a specific sensor type", async() => {
const toBeNotified = listenFilteredSensorUpdates(listenerManager, {
sensors: [accelerometerType]
});

const notToBeNotified = failOnListenFilteredSensorUpdates(listenerManager, {
sensors: [locationType]
});

const sensorRecord = buildFakeSensorRecords(accelerometerType, nodeA.id, [sensorRecord1, sensorRecord2]);
listenerManager.notify(sensorRecord);

await expectAsync(toBeNotified).toBeResolvedTo(sensorRecord);
await expectAsync(notToBeNotified).toBeResolved();
});

it("notifies the listeners registered for a specific node", async() => {
const toBeNotified = listenFilteredSensorUpdates(listenerManager, {
nodes: [nodeA]
});

const notToBeNotified = failOnListenFilteredSensorUpdates(listenerManager, {
nodes: [nodeB]
});

const sensorRecord = buildFakeSensorRecords(accelerometerType, nodeA.id, [sensorRecord1, sensorRecord2]);
listenerManager.notify(sensorRecord);

await expectAsync(toBeNotified).toBeResolvedTo(sensorRecord);
await expectAsync(notToBeNotified).toBeResolved();
});

it("notifies all listeners registered for a specific node and sensor type", async() => {
const globalListener = listenFilteredSensorUpdates(listenerManager, {});
const toBeNotified = listenFilteredSensorUpdates(listenerManager, {
nodes: [nodeA],
sensors: [accelerometerType]
});

const notToBeNotified = failOnListenFilteredSensorUpdates(listenerManager, {
nodes: [nodeA],
sensors: [locationType]
});
const notToBeNotified2= failOnListenFilteredSensorUpdates(listenerManager, {
nodes: [nodeB],
sensors: [accelerometerType]
});

const sensorRecord = buildFakeSensorRecords(accelerometerType, nodeA.id, [sensorRecord1, sensorRecord2]);
listenerManager.notify(sensorRecord);

await expectAsync(globalListener).toBeResolvedTo(sensorRecord);
await expectAsync(toBeNotified).toBeResolvedTo(sensorRecord);
await expectAsync(notToBeNotified).toBeResolved();
await expectAsync(notToBeNotified2).toBeResolved();
});

it("notifies all registered listeners for their specific filtering requirements", () => {
const listenerGlobal = listenFilteredSensorUpdatesWithSpy(listenerManager, {});
const listenerAccLocA = listenFilteredSensorUpdatesWithSpy(listenerManager, {
nodes: [nodeA],
sensors: [accelerometerType, locationType]
});

const listenerAccB = listenFilteredSensorUpdatesWithSpy(listenerManager, {
nodes: [nodeB],
sensors: [accelerometerType]
});

const sensorRecordAccA = buildFakeSensorRecords(accelerometerType, nodeA.id, [sensorRecord1, sensorRecord2]);
const sensorRecordAccB = buildFakeSensorRecords(accelerometerType, nodeB.id, [sensorRecord1, sensorRecord2]);
const sensorRecordLocA = buildFakeSensorRecords(locationType, nodeA.id, [sensorRecord1, sensorRecord2]);
const sensorRecordLocB = buildFakeSensorRecords(locationType, nodeB.id, [sensorRecord1, sensorRecord2]);

listenerManager.notify(sensorRecordAccA);
listenerManager.notify(sensorRecordAccB);
listenerManager.notify(sensorRecordLocA);
listenerManager.notify(sensorRecordLocB);

expect(listenerGlobal.calls.allArgs()).toEqual([[sensorRecordAccA], [sensorRecordAccB], [sensorRecordLocA], [sensorRecordLocB]]);
expect(listenerAccLocA.calls.allArgs()).toEqual([[sensorRecordAccA], [sensorRecordLocA]]);
expect(listenerAccB.calls.allArgs()).toEqual([[sensorRecordAccB]]);
});
});

function listenFilteredSensorUpdates(
listenerManager: SensorListenerManager,
filters: ListenerFilter
): Promise<SensorRecord<any>> {
return new Promise((resolve) => listenerManager.add(sensorRecords => resolve(sensorRecords), filters));
}

function listenFilteredSensorUpdatesWithSpy(
listenerManager: SensorListenerManager,
filters: ListenerFilter
) {
const listener = jasmine.createSpy();
listenerManager.add((sensorRecords) => listener(sensorRecords), filters);
return listener;
}

function failOnListenFilteredSensorUpdates(
listenerManager: SensorListenerManager,
filters: ListenerFilter,
timeout: number = 100,
): Promise<void> {
return new Promise((resolve, reject) => {
listenerManager.add(() => reject("Listener should not be called"), filters);
setTimeout(resolve, timeout);
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ describe("TriAxial record messaging service", () => {
const nodeId = "testNode";
const protocol = getFakeMessagingProtocol();

let callbackManager;
let listenerManager;
let recordMessagingService: TriAxialRecordMessagingService;

beforeEach(() => {
callbackManager = jasmine.createSpyObj("callbackManagerSpy", ['notifyAll']);
listenerManager = jasmine.createSpyObj("listenerManagerSpy", ['notify']);
recordMessagingService = new TriAxialRecordMessagingService();
recordMessagingService.setProtocol(protocol);
recordMessagingService.setCallbackManager(callbackManager);
recordMessagingService.setListenerManager(listenerManager);
spyOn(recordMessagingService, "decodeSamples").and.callThrough();
});

Expand All @@ -23,15 +23,15 @@ describe("TriAxial record messaging service", () => {
recordMessagingService.onMessageReceived(messageEvent);

expect(recordMessagingService.decodeSamples).not.toHaveBeenCalled();
expect(callbackManager.notifyAll).not.toHaveBeenCalled();
expect(listenerManager.notify).not.toHaveBeenCalled();
});

it("does nothing when receives a messages without data", () => {
const messageEvent = buildFakeMessageEvent(nodeId, protocol.newRecordMessagePath);
recordMessagingService.onMessageReceived(messageEvent);

expect(recordMessagingService.decodeSamples).not.toHaveBeenCalled();
expect(callbackManager.notifyAll).not.toHaveBeenCalled();
expect(listenerManager.notify).not.toHaveBeenCalled();
});

it("decodes the message data building a new record", () => {
Expand Down Expand Up @@ -68,6 +68,6 @@ describe("TriAxial record messaging service", () => {
recordMessagingService.onMessageReceived(messageEvent);

expect(recordMessagingService.decodeSamples).toHaveBeenCalledWith(messageEvent);
expect(callbackManager.notifyAll).toHaveBeenCalled();
expect(listenerManager.notify).toHaveBeenCalled();
});
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CollectorManager, PrepareError } from "../collector-manager";
import { SensorCallback, SensorCallbackManager } from "../../sensor-callback-manager";
import { ListenerFilter, SensorListener, SensorListenerManager } from "../../sensor-listener-manager";
import { Node } from "../../node";
import { MessagingClient } from "../../communication/messaging/messaging-client";
import { SensorType } from "../../sensors/sensor-type";
Expand All @@ -10,7 +10,7 @@ export class CollectorManagerImpl implements CollectorManager {
constructor(
private sensor: SensorType,
private messagingClient: MessagingClient,
private callbackManager: SensorCallbackManager,
private listenerManager: SensorListenerManager,
) {
}

Expand Down Expand Up @@ -62,15 +62,15 @@ export class CollectorManagerImpl implements CollectorManager {
await this.messagingClient.sendStopMessage(node);
}

listenSensorUpdates(callback: SensorCallback): number {
return this.callbackManager.add(callback, this.sensor);
addSensorListener(listener: SensorListener, filters?: ListenerFilter): number {
return this.listenerManager.add(listener, filters);
}

stopListenSensorUpdates(listenerId?: number) {
removeSensorListener(listenerId?: number) {
if (typeof listenerId === "number") {
this.callbackManager.remove(listenerId);
this.listenerManager.remove(listenerId);
} else {
this.callbackManager.removeAllForEvent(this.sensor);
this.listenerManager.removeAll();
}
}
}
Loading

0 comments on commit 42ec2a4

Please sign in to comment.