Added unit tests

This commit is contained in:
Jeremy 2025-10-05 14:46:37 -05:00
parent c1b898296b
commit 8f1e334473
2 changed files with 116 additions and 72 deletions

View file

@ -100,92 +100,104 @@ describe(SearchController.name, () => {
expect(body).toEqual(errorDto.badRequest(['isMotion must be a boolean value'])); expect(body).toEqual(errorDto.badRequest(['isMotion must be a boolean value']));
}); });
describe('POST /search/random', () => { it('should reject an order as not an enum', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer()).post('/search/metadata').send({ order: 'invalid' });
await request(ctx.getHttpServer()).post('/search/random'); expect(status).toBe(400);
expect(ctx.authenticate).toHaveBeenCalled(); expect(body).toEqual(errorDto.badRequest(['order must be one of the following values: asc, desc']));
});
it('should reject if withStacked is not a boolean', async () => {
const { status, body } = await request(ctx.getHttpServer())
.post('/search/random')
.send({ withStacked: 'immich' });
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['withStacked must be a boolean value']));
});
it('should reject if withPeople is not a boolean', async () => {
const { status, body } = await request(ctx.getHttpServer())
.post('/search/random')
.send({ withPeople: 'immich' });
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['withPeople must be a boolean value']));
});
}); });
describe('POST /search/smart', () => { it('should reject an orderBy as not an enum', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer()).post('/search/metadata').send({ orderBy: 'invalid' });
await request(ctx.getHttpServer()).post('/search/smart'); expect(status).toBe(400);
expect(ctx.authenticate).toHaveBeenCalled(); expect(body).toEqual(
}); errorDto.badRequest(['orderBy must be one of the following values: DATE_ADDED, DATE_TAKEN']),
);
});
});
describe('POST /search/random', () => {
it('should be an authenticated route', async () => {
await request(ctx.getHttpServer()).post('/search/random');
expect(ctx.authenticate).toHaveBeenCalled();
}); });
describe('GET /search/explore', () => { it('should reject if withStacked is not a boolean', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer())
await request(ctx.getHttpServer()).get('/search/explore'); .post('/search/random')
expect(ctx.authenticate).toHaveBeenCalled(); .send({ withStacked: 'immich' });
}); expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['withStacked must be a boolean value']));
}); });
describe('POST /search/person', () => { it('should reject if withPeople is not a boolean', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer()).post('/search/random').send({ withPeople: 'immich' });
await request(ctx.getHttpServer()).get('/search/person'); expect(status).toBe(400);
expect(ctx.authenticate).toHaveBeenCalled(); expect(body).toEqual(errorDto.badRequest(['withPeople must be a boolean value']));
}); });
});
it('should require a name', async () => { describe('POST /search/smart', () => {
const { status, body } = await request(ctx.getHttpServer()).get('/search/person').send({}); it('should be an authenticated route', async () => {
expect(status).toBe(400); await request(ctx.getHttpServer()).post('/search/smart');
expect(body).toEqual(errorDto.badRequest(['name should not be empty', 'name must be a string'])); expect(ctx.authenticate).toHaveBeenCalled();
}); });
});
describe('GET /search/explore', () => {
it('should be an authenticated route', async () => {
await request(ctx.getHttpServer()).get('/search/explore');
expect(ctx.authenticate).toHaveBeenCalled();
});
});
describe('POST /search/person', () => {
it('should be an authenticated route', async () => {
await request(ctx.getHttpServer()).get('/search/person');
expect(ctx.authenticate).toHaveBeenCalled();
}); });
describe('GET /search/places', () => { it('should require a name', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer()).get('/search/person').send({});
await request(ctx.getHttpServer()).get('/search/places'); expect(status).toBe(400);
expect(ctx.authenticate).toHaveBeenCalled(); expect(body).toEqual(errorDto.badRequest(['name should not be empty', 'name must be a string']));
}); });
});
it('should require a name', async () => { describe('GET /search/places', () => {
const { status, body } = await request(ctx.getHttpServer()).get('/search/places').send({}); it('should be an authenticated route', async () => {
expect(status).toBe(400); await request(ctx.getHttpServer()).get('/search/places');
expect(body).toEqual(errorDto.badRequest(['name should not be empty', 'name must be a string'])); expect(ctx.authenticate).toHaveBeenCalled();
});
}); });
describe('GET /search/cities', () => { it('should require a name', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer()).get('/search/places').send({});
await request(ctx.getHttpServer()).get('/search/cities'); expect(status).toBe(400);
expect(ctx.authenticate).toHaveBeenCalled(); expect(body).toEqual(errorDto.badRequest(['name should not be empty', 'name must be a string']));
}); });
});
describe('GET /search/cities', () => {
it('should be an authenticated route', async () => {
await request(ctx.getHttpServer()).get('/search/cities');
expect(ctx.authenticate).toHaveBeenCalled();
});
});
describe('GET /search/suggestions', () => {
it('should be an authenticated route', async () => {
await request(ctx.getHttpServer()).get('/search/suggestions');
expect(ctx.authenticate).toHaveBeenCalled();
}); });
describe('GET /search/suggestions', () => { it('should require a type', async () => {
it('should be an authenticated route', async () => { const { status, body } = await request(ctx.getHttpServer()).get('/search/suggestions').send({});
await request(ctx.getHttpServer()).get('/search/suggestions'); expect(status).toBe(400);
expect(ctx.authenticate).toHaveBeenCalled(); expect(body).toEqual(
}); errorDto.badRequest([
'type should not be empty',
it('should require a type', async () => { expect.stringContaining('type must be one of the following values:'),
const { status, body } = await request(ctx.getHttpServer()).get('/search/suggestions').send({}); ]),
expect(status).toBe(400); );
expect(body).toEqual(
errorDto.badRequest([
'type should not be empty',
expect.stringContaining('type must be one of the following values:'),
]),
);
});
}); });
}); });
}); });

View file

@ -1,6 +1,7 @@
import { BadRequestException } from '@nestjs/common'; import { BadRequestException } from '@nestjs/common';
import { mapAsset } from 'src/dtos/asset-response.dto'; import { mapAsset } from 'src/dtos/asset-response.dto';
import { SearchSuggestionType } from 'src/dtos/search.dto'; import { SearchSuggestionType } from 'src/dtos/search.dto';
import { AssetOrder, AssetOrderBy } from 'src/enum';
import { SearchService } from 'src/services/search.service'; import { SearchService } from 'src/services/search.service';
import { assetStub } from 'test/fixtures/asset.stub'; import { assetStub } from 'test/fixtures/asset.stub';
import { authStub } from 'test/fixtures/auth.stub'; import { authStub } from 'test/fixtures/auth.stub';
@ -23,6 +24,37 @@ describe(SearchService.name, () => {
expect(sut).toBeDefined(); expect(sut).toBeDefined();
}); });
describe('searchMetadata', () => {
it('should pass options to search', async () => {
mocks.search.searchMetadata.mockResolvedValue({
items: [],
hasNextPage: false,
});
await sut.searchMetadata(authStub.user1, {});
expect(mocks.search.searchMetadata).toHaveBeenCalledWith(
{ page: 1, size: 250 },
{
orderBy: AssetOrderBy.DateTaken,
orderDirection: AssetOrder.Desc,
userIds: [authStub.user1.user.id],
},
);
const pagination = { page: 2, size: 100 };
const dto = { order: AssetOrder.Asc, orderBy: AssetOrderBy.DateAdded, ...pagination };
await sut.searchMetadata(authStub.user1, dto);
expect(mocks.search.searchMetadata).toHaveBeenCalledWith(pagination, {
...dto,
orderBy: AssetOrderBy.DateAdded,
orderDirection: AssetOrder.Asc,
userIds: [authStub.user1.user.id],
});
});
});
describe('searchPerson', () => { describe('searchPerson', () => {
it('should pass options to search', async () => { it('should pass options to search', async () => {
const { name } = personStub.withName; const { name } = personStub.withName;