good forst commit
This commit is contained in:
@@ -34,70 +34,76 @@ describe('SearchService', () => {
|
||||
expect(searchPkg.configureIndex).toHaveBeenCalledWith(mockClient);
|
||||
});
|
||||
|
||||
it('always filters by tenantId', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('tnt-1', 'test');
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'test',
|
||||
expect.objectContaining({ filter: 'tenantId = "tnt-1"' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns hits and total', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [{ id: 'msg-1', content: 'hello' }], totalHits: 1 });
|
||||
const result = await service.search('hello');
|
||||
const result = await service.search('tnt-1', 'hello');
|
||||
expect(result.hits).toHaveLength(1);
|
||||
expect(result.total).toBe(1);
|
||||
expect(result.query).toBe('hello');
|
||||
});
|
||||
|
||||
it('searches with no filter when no groupId or tags', async () => {
|
||||
it('applies sourceGroupId filter alongside tenant', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('test');
|
||||
expect(mockSearch).toHaveBeenCalledWith('test', expect.objectContaining({ filter: undefined }));
|
||||
});
|
||||
|
||||
it('applies sourceGroupId filter', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('hello', 'grp-1');
|
||||
await service.search('tnt-1', 'hello', 'grp-1');
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'hello',
|
||||
expect.objectContaining({ filter: 'sourceGroupId = "grp-1"' }),
|
||||
expect.objectContaining({ filter: 'tenantId = "tnt-1" AND sourceGroupId = "grp-1"' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('applies tags filter', async () => {
|
||||
it('applies tags filter alongside tenant', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('hello', undefined, ['#important']);
|
||||
await service.search('tnt-1', 'hello', undefined, ['#important']);
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'hello',
|
||||
expect.objectContaining({ filter: 'tags = "#important"' }),
|
||||
expect.objectContaining({ filter: 'tenantId = "tnt-1" AND tags = "#important"' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('combines groupId and tags filters with AND', async () => {
|
||||
it('combines groupId and tags filters with AND, all behind tenant', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('hello', 'grp-1', ['#important', '#event']);
|
||||
await service.search('tnt-1', 'hello', 'grp-1', ['#important', '#event']);
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'hello',
|
||||
expect.objectContaining({
|
||||
filter: 'sourceGroupId = "grp-1" AND tags = "#important" AND tags = "#event"',
|
||||
filter:
|
||||
'tenantId = "tnt-1" AND sourceGroupId = "grp-1" AND tags = "#important" AND tags = "#event"',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('defaults page to 1 and hitsPerPage to 20', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('hello');
|
||||
await service.search('tnt-1', 'hello');
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'hello',
|
||||
expect.objectContaining({ page: 1, hitsPerPage: 20 }),
|
||||
);
|
||||
});
|
||||
|
||||
it('escapes double-quotes in groupId to prevent filter injection', async () => {
|
||||
it('escapes double-quotes in filter values to prevent injection', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('hello', 'grp"1"OR id EXISTS');
|
||||
await service.search('tnt-1', 'hello', 'grp"1"OR id EXISTS');
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'hello',
|
||||
expect.objectContaining({ filter: 'sourceGroupId = "grp\\"1\\"OR id EXISTS"' }),
|
||||
expect.objectContaining({
|
||||
filter: 'tenantId = "tnt-1" AND sourceGroupId = "grp\\"1\\"OR id EXISTS"',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('clamps page to minimum 1 and limit to maximum 100', async () => {
|
||||
it('clamps page to min 1 and limit to max 100', async () => {
|
||||
mockSearch.mockResolvedValue({ hits: [], totalHits: 0 });
|
||||
await service.search('hello', undefined, undefined, 0, 999);
|
||||
await service.search('tnt-1', 'hello', undefined, undefined, 0, 999);
|
||||
expect(mockSearch).toHaveBeenCalledWith(
|
||||
'hello',
|
||||
expect.objectContaining({ page: 1, hitsPerPage: 100 }),
|
||||
|
||||
Reference in New Issue
Block a user