Skip to content

Commit fac12f3

Browse files
committed
hasher tests
1 parent 1562d05 commit fac12f3

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import { defaultHasher } from '../src';
2+
3+
describe('defaultHasher', () => {
4+
test('should create a hasher instance', () => {
5+
const hasher = defaultHasher();
6+
expect(hasher).toBeDefined();
7+
expect(typeof hasher.update).toBe('function');
8+
expect(typeof hasher.digest).toBe('function');
9+
});
10+
11+
test('should return consistent hex hash for the same input', () => {
12+
const input = 'test data';
13+
const hash1 = defaultHasher().update(input).digest('hex');
14+
const hash2 = defaultHasher().update(input).digest('hex');
15+
16+
expect(hash1).toBe(hash2);
17+
expect(typeof hash1).toBe('string');
18+
expect(hash1.length).toBeGreaterThan(0);
19+
});
20+
21+
test('should return different hashes for different inputs', () => {
22+
const hash1 = defaultHasher().update('input1').digest('hex');
23+
const hash2 = defaultHasher().update('input2').digest('hex');
24+
25+
expect(hash1).not.toBe(hash2);
26+
});
27+
28+
test('should support chaining update calls', () => {
29+
const hash1 = defaultHasher()
30+
.update('part1')
31+
.update('part2')
32+
.digest('hex');
33+
34+
const hash2 = defaultHasher()
35+
.update('part1part2')
36+
.digest('hex');
37+
38+
expect(hash1).toBe(hash2);
39+
});
40+
41+
test('should handle Buffer inputs', () => {
42+
const buffer = Buffer.from('test data');
43+
const hash = defaultHasher().update(buffer).digest('hex');
44+
45+
expect(hash).toBeDefined();
46+
expect(typeof hash).toBe('string');
47+
});
48+
49+
test('should return Buffer when digest is called without encoding', () => {
50+
const hash = defaultHasher().update('test').digest();
51+
52+
expect(Buffer.isBuffer(hash)).toBe(true);
53+
expect(hash.length).toBe(16); // 128 bits = 16 bytes
54+
});
55+
56+
test('should handle JSON stringified objects', () => {
57+
const obj = { key: 'value', nested: { prop: 123 } };
58+
const hash1 = defaultHasher().update(JSON.stringify(obj)).digest('hex');
59+
const hash2 = defaultHasher().update(JSON.stringify(obj)).digest('hex');
60+
61+
expect(hash1).toBe(hash2);
62+
});
63+
64+
test('should handle empty strings', () => {
65+
const hash = defaultHasher().update('').digest('hex');
66+
67+
expect(hash).toBeDefined();
68+
expect(typeof hash).toBe('string');
69+
});
70+
71+
test('should handle large inputs', () => {
72+
const largeString = 'x'.repeat(10000);
73+
const hash = defaultHasher().update(largeString).digest('hex');
74+
75+
expect(hash).toBeDefined();
76+
expect(typeof hash).toBe('string');
77+
});
78+
79+
test('should handle unicode characters', () => {
80+
const unicode = '你好世界 🌍 مرحبا';
81+
const hash = defaultHasher().update(unicode).digest('hex');
82+
83+
expect(hash).toBeDefined();
84+
expect(typeof hash).toBe('string');
85+
});
86+
87+
test('should produce consistent hashes for mixed string and Buffer updates', () => {
88+
const hash1 = defaultHasher()
89+
.update('hello')
90+
.update(Buffer.from('world'))
91+
.digest('hex');
92+
93+
const hash2 = defaultHasher()
94+
.update(Buffer.from('hello'))
95+
.update('world')
96+
.digest('hex');
97+
98+
expect(hash1).toBe(hash2);
99+
});
100+
});
101+
102+
describe('Hasher interface compatibility', () => {
103+
test('should be compatible with crypto.createHash API pattern', () => {
104+
// This tests that the API matches the pattern used to replace crypto.createHash('md5')
105+
const data = JSON.stringify({ test: 'data' });
106+
107+
// Old pattern: crypto.createHash('md5').update(data).digest('hex')
108+
// New pattern: defaultHasher().update(data).digest('hex')
109+
const hash = defaultHasher().update(data).digest('hex');
110+
111+
expect(hash).toBeDefined();
112+
expect(typeof hash).toBe('string');
113+
});
114+
115+
test('should support digest() without encoding for Buffer result', () => {
116+
// Old pattern: crypto.createHash('md5').update(data).digest()
117+
// New pattern: defaultHasher().update(data).digest()
118+
const data = JSON.stringify({ test: 'data' });
119+
const digestBuffer = defaultHasher().update(data).digest();
120+
121+
expect(Buffer.isBuffer(digestBuffer)).toBe(true);
122+
expect(digestBuffer.length).toBe(16);
123+
});
124+
125+
test('should handle the version() function pattern from PreAggregations', () => {
126+
// Testing the pattern: defaultHasher().update(JSON.stringify(cacheKey)).digest()
127+
const cacheKey = ['2024', '01', 'users'];
128+
const digestBuffer = defaultHasher().update(JSON.stringify(cacheKey)).digest();
129+
130+
expect(Buffer.isBuffer(digestBuffer)).toBe(true);
131+
132+
// Should be able to read bytes from the buffer like the old code did
133+
const firstByte = digestBuffer.readUInt8(0);
134+
expect(typeof firstByte).toBe('number');
135+
expect(firstByte).toBeGreaterThanOrEqual(0);
136+
expect(firstByte).toBeLessThanOrEqual(255);
137+
});
138+
});
139+
140+
describe('Hash consistency across different data types', () => {
141+
test('string vs Buffer with same content should produce same hash', () => {
142+
const str = 'test content';
143+
const buf = Buffer.from(str);
144+
145+
const hashFromString = defaultHasher().update(str).digest('hex');
146+
const hashFromBuffer = defaultHasher().update(buf).digest('hex');
147+
148+
expect(hashFromString).toBe(hashFromBuffer);
149+
});
150+
151+
test('Buffer digest should be consistent', () => {
152+
const input = 'consistent test';
153+
const digest1 = defaultHasher().update(input).digest();
154+
const digest2 = defaultHasher().update(input).digest();
155+
156+
expect(digest1.equals(digest2)).toBe(true);
157+
});
158+
});

0 commit comments

Comments
 (0)