Skip to content

Commit bb48a94

Browse files
authored
Test/search (#215)
* test(search): test elasticsearch module * test(search): add search test cases
1 parent 67820a6 commit bb48a94

File tree

5 files changed

+2151
-130
lines changed

5 files changed

+2151
-130
lines changed

src/background-jobs/elasticsearch/es-sync.processor.spec.ts

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ describe('EsSyncProcessor', () => {
3232
bulk: jest.fn(),
3333
updateByQuery: jest.fn(),
3434
deleteByQuery: jest.fn(),
35+
get: jest.fn(),
3536
};
3637

3738
const mock_user_follows_repository = {
@@ -184,6 +185,7 @@ describe('EsSyncProcessor', () => {
184185
const mock_tweet = {
185186
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
186187
content: 'Reply tweet',
188+
type: TweetType.REPLY,
187189
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
188190
user: {
189191
name: 'Test User',
@@ -213,6 +215,260 @@ describe('EsSyncProcessor', () => {
213215
}),
214216
});
215217
});
218+
219+
it('should use existing parent_id from ES when not provided in job data', async () => {
220+
const mock_tweet = {
221+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
222+
content: 'Reply tweet',
223+
type: TweetType.REPLY,
224+
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
225+
user: {
226+
name: 'Test User',
227+
username: 'testuser',
228+
} as User,
229+
} as Tweet;
230+
231+
const job = {
232+
data: {
233+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
234+
parent_id: undefined,
235+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
236+
},
237+
} as Job;
238+
239+
const existing_es_doc = {
240+
_source: {
241+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
242+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
243+
},
244+
};
245+
246+
mock_tweets_repository.findOne.mockResolvedValue(mock_tweet);
247+
mock_elasticsearch_service.get.mockResolvedValue(existing_es_doc as any);
248+
mock_elasticsearch_service.index.mockResolvedValue({} as any);
249+
250+
await processor.handleIndexTweet(job);
251+
252+
expect(mock_elasticsearch_service.get).toHaveBeenCalledWith({
253+
index: ELASTICSEARCH_INDICES.TWEETS,
254+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
255+
});
256+
expect(mock_elasticsearch_service.index).toHaveBeenCalledWith({
257+
index: ELASTICSEARCH_INDICES.TWEETS,
258+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
259+
document: expect.objectContaining({
260+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
261+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
262+
}),
263+
});
264+
});
265+
266+
it('should use existing conversation_id from ES when not provided in job data', async () => {
267+
const mock_tweet = {
268+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
269+
content: 'Reply tweet',
270+
type: TweetType.REPLY,
271+
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
272+
user: {
273+
name: 'Test User',
274+
username: 'testuser',
275+
} as User,
276+
} as Tweet;
277+
278+
const job = {
279+
data: {
280+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
281+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
282+
conversation_id: undefined,
283+
},
284+
} as Job;
285+
286+
const existing_es_doc = {
287+
_source: {
288+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
289+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
290+
},
291+
};
292+
293+
mock_tweets_repository.findOne.mockResolvedValue(mock_tweet);
294+
mock_elasticsearch_service.get.mockResolvedValue(existing_es_doc as any);
295+
mock_elasticsearch_service.index.mockResolvedValue({} as any);
296+
297+
await processor.handleIndexTweet(job);
298+
299+
expect(mock_elasticsearch_service.get).toHaveBeenCalledWith({
300+
index: ELASTICSEARCH_INDICES.TWEETS,
301+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
302+
});
303+
expect(mock_elasticsearch_service.index).toHaveBeenCalledWith({
304+
index: ELASTICSEARCH_INDICES.TWEETS,
305+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
306+
document: expect.objectContaining({
307+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
308+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
309+
}),
310+
});
311+
});
312+
313+
it('should use existing parent_id and conversation_id from ES when both not provided', async () => {
314+
const mock_tweet = {
315+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
316+
content: 'Reply tweet',
317+
type: TweetType.REPLY,
318+
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
319+
user: {
320+
name: 'Test User',
321+
username: 'testuser',
322+
} as User,
323+
} as Tweet;
324+
325+
const job = {
326+
data: {
327+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
328+
parent_id: undefined,
329+
conversation_id: undefined,
330+
},
331+
} as Job;
332+
333+
const existing_es_doc = {
334+
_source: {
335+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
336+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
337+
},
338+
};
339+
340+
mock_tweets_repository.findOne.mockResolvedValue(mock_tweet);
341+
mock_elasticsearch_service.get.mockResolvedValue(existing_es_doc as any);
342+
mock_elasticsearch_service.index.mockResolvedValue({} as any);
343+
344+
await processor.handleIndexTweet(job);
345+
346+
expect(mock_elasticsearch_service.get).toHaveBeenCalledWith({
347+
index: ELASTICSEARCH_INDICES.TWEETS,
348+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
349+
});
350+
expect(mock_elasticsearch_service.index).toHaveBeenCalledWith({
351+
index: ELASTICSEARCH_INDICES.TWEETS,
352+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
353+
document: expect.objectContaining({
354+
parent_id: '6ba9c7cf-302b-433f-8642-50de81ef0372',
355+
conversation_id: '4fa1b0f4-a059-4b6f-ab1f-137217d33d3c',
356+
}),
357+
});
358+
});
359+
360+
it('should skip ES lookup when tweet type is TWEET even if IDs not provided', async () => {
361+
const mock_tweet = {
362+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
363+
content: 'Regular tweet',
364+
type: TweetType.TWEET,
365+
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
366+
user: {
367+
name: 'Test User',
368+
username: 'testuser',
369+
} as User,
370+
} as Tweet;
371+
372+
const job = {
373+
data: {
374+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
375+
parent_id: undefined,
376+
conversation_id: undefined,
377+
},
378+
} as Job;
379+
380+
mock_tweets_repository.findOne.mockResolvedValue(mock_tweet);
381+
mock_elasticsearch_service.index.mockResolvedValue({} as any);
382+
383+
await processor.handleIndexTweet(job);
384+
385+
expect(mock_elasticsearch_service.get).not.toHaveBeenCalled();
386+
expect(mock_elasticsearch_service.index).toHaveBeenCalled();
387+
});
388+
389+
it('should handle ES get error gracefully and continue with indexing', async () => {
390+
const mock_tweet = {
391+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
392+
content: 'Reply tweet',
393+
type: TweetType.REPLY,
394+
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
395+
user: {
396+
name: 'Test User',
397+
username: 'testuser',
398+
} as User,
399+
} as Tweet;
400+
401+
const job = {
402+
data: {
403+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
404+
parent_id: undefined,
405+
conversation_id: undefined,
406+
},
407+
} as Job;
408+
409+
mock_tweets_repository.findOne.mockResolvedValue(mock_tweet);
410+
mock_elasticsearch_service.get.mockRejectedValue(new Error('Document not found'));
411+
mock_elasticsearch_service.index.mockResolvedValue({} as any);
412+
413+
const logger_spy = jest.spyOn(Logger.prototype, 'debug');
414+
415+
await processor.handleIndexTweet(job);
416+
417+
expect(logger_spy).toHaveBeenCalledWith(
418+
'No existing ES document for tweet 0c059899-f706-4c8f-97d7-ba2e9fc22d6d'
419+
);
420+
expect(mock_elasticsearch_service.index).toHaveBeenCalledWith({
421+
index: ELASTICSEARCH_INDICES.TWEETS,
422+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
423+
document: expect.objectContaining({
424+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
425+
}),
426+
});
427+
});
428+
429+
it('should prefer job data IDs over existing ES document IDs', async () => {
430+
const mock_tweet = {
431+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
432+
content: 'Reply tweet',
433+
type: TweetType.REPLY,
434+
user_id: '1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6',
435+
user: {
436+
name: 'Test User',
437+
username: 'testuser',
438+
} as User,
439+
} as Tweet;
440+
441+
const job = {
442+
data: {
443+
tweet_id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
444+
parent_id: 'new-parent-id',
445+
conversation_id: 'new-conversation-id',
446+
},
447+
} as Job;
448+
449+
const existing_es_doc = {
450+
_source: {
451+
parent_id: 'old-parent-id',
452+
conversation_id: 'old-conversation-id',
453+
},
454+
};
455+
456+
mock_tweets_repository.findOne.mockResolvedValue(mock_tweet);
457+
mock_elasticsearch_service.get.mockResolvedValue(existing_es_doc as any);
458+
mock_elasticsearch_service.index.mockResolvedValue({} as any);
459+
460+
await processor.handleIndexTweet(job);
461+
462+
expect(mock_elasticsearch_service.get).not.toHaveBeenCalled();
463+
expect(mock_elasticsearch_service.index).toHaveBeenCalledWith({
464+
index: ELASTICSEARCH_INDICES.TWEETS,
465+
id: '0c059899-f706-4c8f-97d7-ba2e9fc22d6d',
466+
document: expect.objectContaining({
467+
parent_id: 'new-parent-id',
468+
conversation_id: 'new-conversation-id',
469+
}),
470+
});
471+
});
216472
});
217473

218474
describe('handleDeleteTweet', () => {

0 commit comments

Comments
 (0)