102 lines
2.7 KiB
TypeScript

import { describe, test, expect, beforeEach } from '@jest/globals';
import { RhizomeNode, Lossless, createDelta } from '@src';
import { CustomResolver } from '@src/views/resolvers/custom-resolvers';
class RunningAveragePlugin {
readonly name = 'running-average' as const;
initialize() {
return { sum: 0, count: 0 };
}
update(currentState: {sum: number, count: number}, newValue: unknown, _delta: any) {
const numValue = typeof newValue === 'number' ? newValue : 0;
return {
sum: currentState.sum + numValue,
count: currentState.count + 1
};
}
resolve(state: {sum: number, count: number}) {
return state.count > 0 ? state.sum / state.count : 0;
}
}
describe('RunningAveragePlugin', () => {
let node: RhizomeNode;
let lossless: Lossless;
beforeEach(() => {
node = new RhizomeNode();
lossless = new Lossless(node);
});
test('should calculate running average of numeric values', () => {
// First score (10)
lossless.ingestDelta(
createDelta('user1', 'host1')
.withTimestamp(1000)
.setProperty('player1', 'score', 10, 'game')
.buildV1()
);
// Second score (20)
lossless.ingestDelta(
createDelta('user1', 'host1')
.withTimestamp(2000)
.setProperty('player1', 'score', 20, 'game')
.buildV1()
);
// Third score (30)
lossless.ingestDelta(
createDelta('user1', 'host1')
.withTimestamp(3000)
.setProperty('player1', 'score', 30, 'game')
.buildV1()
);
const resolver = new CustomResolver(lossless, {
score: new RunningAveragePlugin()
});
const result = resolver.resolve();
expect(result).toBeDefined();
expect(result!['player1'].properties.score).toBe(20); // (10 + 20 + 30) / 3 = 20
});
test('should handle non-numeric values gracefully', () => {
lossless.ingestDelta(
createDelta('user1', 'host1')
.withTimestamp(1000)
.setProperty('test1', 'value', 'not a number', 'test')
.buildV1()
);
lossless.ingestDelta(
createDelta('user1', 'host1')
.withTimestamp(2000)
.setProperty('test1', 'value', 10, 'test')
.buildV1()
);
const resolver = new CustomResolver(lossless, {
value: new RunningAveragePlugin()
});
const result = resolver.resolve();
expect(result).toBeDefined();
// First value is treated as 0, second as 10, average is (0 + 10) / 2 = 5
expect(result!['test1'].properties.value).toBe(5);
});
test('should handle empty state', () => {
const resolver = new CustomResolver(lossless, {
value: new RunningAveragePlugin()
});
const result = resolver.resolve();
expect(result).toEqual({});
});
});