Skip to content

Commit

Permalink
Test property groups and priorities
Browse files Browse the repository at this point in the history
  • Loading branch information
bcopy committed Sep 25, 2024
1 parent 04e10b4 commit 20158d2
Showing 1 changed file with 98 additions and 61 deletions.
159 changes: 98 additions & 61 deletions test/HomiePropertyBuffer.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
// HomiePropertyBuffer.test.ts
import { HomieObserver, HomieEventType, HomieEvent, MqttMessageHandler } from '../src/HomieObserver';
import { HomiePropertyBuffer } from '../src/HomiePropertyBuffer';

class MockMqttClient implements MqttMessageHandler {
private callback: (event: HomieEvent) => void;

constructor(callback: (event: HomieEvent) => void) {
this.callback = callback;
}
constructor(private callback: (event: HomieEvent) => void) {}

handleMessage(topic: string, message: Buffer): void {
console.log(`MockMqttClient handling message: ${topic} - ${message.toString()}`);
const [, deviceId, nodeId, propertyId] = topic.split('/');
const value = message.toString();

if (nodeId === '$state') {
this.callback({
type: HomieEventType.Device,
device: { id: deviceId, nodes: {} }
});
} else if (propertyId === undefined) {
this.callback({
type: HomieEventType.Node,
device: { id: deviceId, nodes: {} },
node: { id: nodeId, properties: {} }
});
} else {
console.log('Calling callback with Property event');
if (propertyId) {
this.callback({
type: HomieEventType.Property,
device: { id: deviceId, nodes: {} },
Expand All @@ -36,9 +18,7 @@ class MockMqttClient implements MqttMessageHandler {
}
}

subscribe(topic: string): void {
console.log(`MockMqttClient subscribed to: ${topic}`);
}
subscribe(topic: string): void {}
}

describe('HomiePropertyBuffer', () => {
Expand All @@ -52,46 +32,103 @@ describe('HomiePropertyBuffer', () => {
propertyBuffer = new HomiePropertyBuffer(observer, 100);
});

it('should buffer updates and emit them', (done) => {
console.log('Starting test');

const updates: any[] = [];
const subscription = propertyBuffer.getBufferedUpdates().subscribe({
next: (bufferedUpdates) => {
console.log('Received buffered updates in test:', bufferedUpdates);
updates.push(...bufferedUpdates);
if (updates.length === 2) {
expect(updates[0]).toEqual(expect.objectContaining({
deviceId: 'device1',
nodeId: 'node1',
propertyId: 'prop1',
value: 'value1'
}));
expect(updates[1]).toEqual(expect.objectContaining({
deviceId: 'device1',
nodeId: 'node1',
propertyId: 'prop2',
value: 'value2'
}));
subscription.unsubscribe();
done();
}
},
error: (err) => {
console.error('Error in test subscription:', err);
done(err);
}
const simulatePropertyUpdates = (updates: [string, string, string, string][]) => {
updates.forEach(([deviceId, nodeId, propertyId, value]) => {
mockMqttClient.handleMessage(`homie/${deviceId}/${nodeId}/${propertyId}`, Buffer.from(value));
});
};

const collectBufferedUpdates = (count: number): Promise<any[]> => {
return new Promise((resolve, reject) => {
const updates: any[] = [];
const subscription = propertyBuffer.getBufferedUpdates().subscribe({
next: (bufferedUpdates) => {
updates.push(...bufferedUpdates);
if (updates.length >= count) {
subscription.unsubscribe();
resolve(updates);
}
},
error: reject
});

setTimeout(() => {
subscription.unsubscribe();
reject(new Error('Test timed out'));
}, 5000);
});
};

it('should buffer updates and emit them', async () => {
const updatePromise = collectBufferedUpdates(2);
simulatePropertyUpdates([
['device1', 'node1', 'prop1', 'value1'],
['device1', 'node1', 'prop2', 'value2']
]);

const updates = await updatePromise;
expect(updates).toHaveLength(2);
expect(updates[0]).toMatchObject({ deviceId: 'device1', nodeId: 'node1', propertyId: 'prop1', value: 'value1' });
expect(updates[1]).toMatchObject({ deviceId: 'device1', nodeId: 'node1', propertyId: 'prop2', value: 'value2' });
});

it('should sort properties by priority', async () => {
propertyBuffer.addPropertyGroup({ name: 'High Priority', properties: ['node1/prop1'], priority: 2 });
propertyBuffer.addPropertyGroup({ name: 'Low Priority', properties: ['node1/prop2'], priority: 1 });

const updatePromise = collectBufferedUpdates(2);
simulatePropertyUpdates([
['device1', 'node1', 'prop2', 'value2'],
['device1', 'node1', 'prop1', 'value1']
]);

const updates = await updatePromise;
expect(updates).toHaveLength(2);
expect(updates[0]).toMatchObject({ propertyId: 'prop1', value: 'value1' });
expect(updates[1]).toMatchObject({ propertyId: 'prop2', value: 'value2' });
});

it('should keep properties together in their group', async () => {
propertyBuffer.addPropertyGroup({
name: 'Group1',
properties: ['node1/prop1', 'node1/prop2', 'node1/prop3'],
priority: 1
});

const updatePromise = collectBufferedUpdates(3);
simulatePropertyUpdates([
['device1', 'node1', 'prop2', 'value2'],
['device1', 'node1', 'prop3', 'value3'],
['device1', 'node1', 'prop1', 'value1']
]);

const updates = await updatePromise;
expect(updates).toHaveLength(3);
expect(updates.map(u => u.propertyId)).toEqual(['prop1', 'prop2', 'prop3']);
});

it('should handle multiple groups with different priorities', async () => {
propertyBuffer.addPropertyGroup({
name: 'Group1',
properties: ['node1/prop1', 'node1/prop2'],
priority: 2
});
propertyBuffer.addPropertyGroup({
name: 'Group2',
properties: ['node1/prop3', 'node1/prop4'],
priority: 1
});

console.log('Simulating MQTT messages');
mockMqttClient.handleMessage('homie/device1/node1/prop1', Buffer.from('value1'));
mockMqttClient.handleMessage('homie/device1/node1/prop2', Buffer.from('value2'));
const updatePromise = collectBufferedUpdates(4);
simulatePropertyUpdates([
['device1', 'node1', 'prop3', 'value3'],
['device1', 'node1', 'prop1', 'value1'],
['device1', 'node1', 'prop4', 'value4'],
['device1', 'node1', 'prop2', 'value2']
]);

// Increase timeout to 5 seconds
setTimeout(() => {
console.log('Test timed out');
subscription.unsubscribe();
done(new Error('Test timed out'));
}, 5000);
const updates = await updatePromise;
expect(updates).toHaveLength(4);
expect(updates.map(u => u.propertyId)).toEqual(['prop1', 'prop2', 'prop3', 'prop4']);
});
});

0 comments on commit 20158d2

Please sign in to comment.