Skip to content

Commit e3b4d8a

Browse files
committed
added merge tests
1 parent 1c2ad41 commit e3b4d8a

1 file changed

Lines changed: 366 additions & 0 deletions

File tree

test/utils/merge.test.ts

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
import { composeFullRepetitionEvent } from '../../src/utils/merge';
2+
import { GroupedEventDBScheme, RepetitionDBScheme } from '@hawk.so/types';
3+
4+
import { diff } from '@n1ru4l/json-patch-plus';
5+
6+
describe('composeFullRepetitionEvent', () => {
7+
const mockOriginalEvent: GroupedEventDBScheme = {
8+
groupHash: 'original-event-1',
9+
totalCount: 1,
10+
catcherType: 'javascript',
11+
payload: {
12+
title: 'Original message',
13+
type: 'error',
14+
addons: JSON.stringify({ userId: 123 }),
15+
context: JSON.stringify({ sessionId: 'abc' }),
16+
},
17+
usersAffected: 1,
18+
visitedBy: [],
19+
timestamp: 1640995200, // 2023-01-01T00:00:00Z
20+
};
21+
22+
beforeEach(() => {
23+
jest.clearAllMocks();
24+
});
25+
26+
describe('when repetition is undefined', () => {
27+
it('should return a deep copy of the original event', () => {
28+
/**
29+
* Arrange
30+
*/
31+
const repetition = undefined;
32+
33+
/**
34+
* Act
35+
*/
36+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
37+
38+
/**
39+
* Assert
40+
*/
41+
expect(result).toEqual(mockOriginalEvent);
42+
expect(result).toMatchObject(mockOriginalEvent);
43+
expect(result.payload).toMatchObject(mockOriginalEvent.payload);
44+
});
45+
});
46+
47+
describe('when repetition.delta is provided (new delta format)', () => {
48+
it('should parse addons and context, apply patch, and stringify fields back', () => {
49+
/**
50+
* Arrange
51+
*/
52+
const delta = diff({
53+
left: mockOriginalEvent.payload,
54+
right: {
55+
...mockOriginalEvent.payload,
56+
title: 'Updated message',
57+
type: 'warning',
58+
},
59+
});
60+
61+
const repetition: RepetitionDBScheme = {
62+
groupHash: 'original-event-1',
63+
timestamp: 1640995200,
64+
delta: JSON.stringify(delta),
65+
};
66+
67+
/**
68+
* Act
69+
*/
70+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
71+
72+
/**
73+
* Assert
74+
*/
75+
expect(result.payload).toEqual({
76+
title: 'Updated message',
77+
type: 'warning',
78+
addons: JSON.stringify({ userId: 123 }),
79+
context: JSON.stringify({ sessionId: 'abc' }),
80+
});
81+
});
82+
83+
it('should handle delta with new fields', () => {
84+
/**
85+
* Arrange
86+
*/
87+
const delta = diff({
88+
left: mockOriginalEvent.payload,
89+
right: {
90+
...mockOriginalEvent.payload,
91+
release: 'v1.0.0',
92+
catcherVersion: '2.0.0',
93+
},
94+
});
95+
96+
const repetition: RepetitionDBScheme = {
97+
groupHash: 'original-event-1',
98+
timestamp: 1640995200,
99+
delta: JSON.stringify(delta),
100+
};
101+
102+
/**
103+
* Act
104+
*/
105+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
106+
107+
/**
108+
* Assert
109+
*/
110+
expect(result.payload).toEqual({
111+
title: 'Original message',
112+
type: 'error',
113+
release: 'v1.0.0',
114+
catcherVersion: '2.0.0',
115+
addons: JSON.stringify({ userId: 123 }),
116+
context: JSON.stringify({ sessionId: 'abc' }),
117+
});
118+
});
119+
});
120+
121+
describe('when repetition.delta is undefined and repetition.payload is undefined', () => {
122+
it('should return the original event unchanged', () => {
123+
/**
124+
* Arrange
125+
*/
126+
const repetition: RepetitionDBScheme = {
127+
groupHash: 'original-event-1',
128+
timestamp: 1640995200,
129+
delta: undefined,
130+
payload: undefined,
131+
};
132+
133+
/**
134+
* Act
135+
*/
136+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
137+
138+
/**
139+
* Assert
140+
*/
141+
expect(result).toEqual(mockOriginalEvent);
142+
expect(result).not.toBe(mockOriginalEvent); // Должна быть глубокая копия
143+
});
144+
});
145+
146+
describe('when repetition.delta is undefined and repetition.payload is provided (old delta format)', () => {
147+
it('should use repetitionAssembler to merge payloads', () => {
148+
/**
149+
* Arrange
150+
*/
151+
const repetition: RepetitionDBScheme = {
152+
groupHash: 'original-event-1',
153+
timestamp: 1640995200,
154+
delta: undefined,
155+
payload: {
156+
title: 'Updated message',
157+
type: 'warning',
158+
release: 'v1.0.0',
159+
},
160+
};
161+
162+
/**
163+
* Act
164+
*/
165+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
166+
167+
/**
168+
* Assert
169+
*/
170+
expect(result.payload).toEqual({
171+
title: 'Updated message',
172+
type: 'warning',
173+
release: 'v1.0.0',
174+
// Addons and context should be, because old format doesn't remove fields
175+
addons: JSON.stringify({ userId: 123 }),
176+
context: JSON.stringify({ sessionId: 'abc' }),
177+
});
178+
});
179+
180+
it('should handle null values in repetition payload', () => {
181+
/**
182+
* Arrange
183+
*/
184+
const repetition: RepetitionDBScheme = {
185+
groupHash: 'original-event-1',
186+
timestamp: 1640995200,
187+
delta: undefined,
188+
payload: {
189+
title: 'Updated title',
190+
type: 'info',
191+
},
192+
};
193+
194+
/**
195+
* Act
196+
*/
197+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
198+
199+
/**
200+
* Assert
201+
*/
202+
expect(result.payload).toEqual({
203+
title: 'Updated title', // repetition value replaces original
204+
type: 'info',
205+
// Addons and context should be, because old format doesn't remove fields
206+
addons: JSON.stringify({ userId: 123 }),
207+
context: JSON.stringify({ sessionId: 'abc' }),
208+
});
209+
});
210+
211+
it('should preserve original value when repetition payload has null', () => {
212+
/**
213+
* Arrange
214+
*/
215+
const repetition: RepetitionDBScheme = {
216+
groupHash: 'original-event-1',
217+
timestamp: 1640995200,
218+
delta: undefined,
219+
payload: {
220+
title: null as any,
221+
type: 'info',
222+
},
223+
};
224+
225+
/**
226+
* Act
227+
*/
228+
const result = composeFullRepetitionEvent(mockOriginalEvent, repetition);
229+
230+
/**
231+
* Assert
232+
*/
233+
expect(result.payload).toEqual({
234+
title: 'Original message', // null в repetition должно сохранить оригинальное значение
235+
type: 'info',
236+
addons: JSON.stringify({ userId: 123 }),
237+
context: JSON.stringify({ sessionId: 'abc' }),
238+
});
239+
});
240+
});
241+
242+
describe('edge cases', () => {
243+
it('should handle empty payload in original event', () => {
244+
/**
245+
* Arrange
246+
*/
247+
const eventWithEmptyPayload: GroupedEventDBScheme = {
248+
groupHash: 'event-4',
249+
totalCount: 1,
250+
catcherType: 'javascript',
251+
payload: {
252+
title: 'Empty event',
253+
},
254+
usersAffected: 1,
255+
visitedBy: [],
256+
timestamp: 1640995200,
257+
};
258+
259+
const delta = diff({
260+
left: eventWithEmptyPayload.payload,
261+
right: {
262+
...eventWithEmptyPayload.payload,
263+
title: 'New message',
264+
},
265+
});
266+
267+
const repetition: RepetitionDBScheme = {
268+
groupHash: 'event-4',
269+
timestamp: 1640995200,
270+
delta: JSON.stringify(delta),
271+
};
272+
273+
/**
274+
* Act
275+
*/
276+
const result = composeFullRepetitionEvent(eventWithEmptyPayload, repetition);
277+
278+
/**
279+
* Assert
280+
*/
281+
expect(result.payload).toEqual({
282+
title: 'New message',
283+
});
284+
});
285+
286+
it('should handle null payload in original event', () => {
287+
/**
288+
* Arrange
289+
*/
290+
const eventWithNullPayload: GroupedEventDBScheme = {
291+
groupHash: 'event-5',
292+
totalCount: 1,
293+
catcherType: 'javascript',
294+
payload: null as any,
295+
usersAffected: 1,
296+
visitedBy: [],
297+
timestamp: 1640995200,
298+
};
299+
300+
const delta = diff({
301+
left: eventWithNullPayload.payload,
302+
right: {
303+
title: 'New message',
304+
},
305+
});
306+
307+
const repetition: RepetitionDBScheme = {
308+
groupHash: 'event-5',
309+
timestamp: 1640995200,
310+
delta: JSON.stringify(delta),
311+
};
312+
313+
/**
314+
* Act
315+
*/
316+
const result = composeFullRepetitionEvent(eventWithNullPayload, repetition);
317+
318+
/**
319+
* Assert
320+
*/
321+
expect(result.payload).toEqual({
322+
title: 'New message',
323+
});
324+
});
325+
326+
it('should handle invalid JSON in addons or context', () => {
327+
/**
328+
* Arrange
329+
*/
330+
const eventWithInvalidJSON: GroupedEventDBScheme = {
331+
groupHash: 'event-6',
332+
totalCount: 1,
333+
catcherType: 'javascript',
334+
payload: {
335+
title: 'Test',
336+
addons: 'invalid json',
337+
context: 'also invalid',
338+
},
339+
usersAffected: 1,
340+
visitedBy: [],
341+
timestamp: 1640995200,
342+
};
343+
344+
const delta = diff({
345+
left: eventWithInvalidJSON.payload,
346+
right: {
347+
...eventWithInvalidJSON.payload,
348+
title: 'Updated',
349+
},
350+
});
351+
352+
const repetition: RepetitionDBScheme = {
353+
groupHash: 'event-6',
354+
timestamp: 1640995200,
355+
delta: JSON.stringify(delta),
356+
};
357+
358+
/**
359+
* Act & Assert
360+
*/
361+
expect(() => {
362+
composeFullRepetitionEvent(eventWithInvalidJSON, repetition);
363+
}).toThrow(); // Должно выбросить ошибку при парсинге невалидного JSON
364+
});
365+
});
366+
});

0 commit comments

Comments
 (0)