RevisionsService: Throw NotInDBError on empty DB result

This adds error handling to various getters, so they throw a
NotInDBError instead of (illegally, according to the type) returning
null.

Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
David Mehren 2021-04-29 15:03:44 +02:00
parent 3861d4beb4
commit a6e245c551
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
2 changed files with 40 additions and 5 deletions

View file

@ -6,6 +6,8 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm'; import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { NotInDBError } from '../errors/errors';
import { LoggerModule } from '../logger/logger.module'; import { LoggerModule } from '../logger/logger.module';
import { AuthorColor } from '../notes/author-color.entity'; import { AuthorColor } from '../notes/author-color.entity';
import { Note } from '../notes/note.entity'; import { Note } from '../notes/note.entity';
@ -25,6 +27,7 @@ import appConfigMock from '../config/mock/app.config.mock';
describe('RevisionsService', () => { describe('RevisionsService', () => {
let service: RevisionsService; let service: RevisionsService;
let revisionRepo: Repository<Revision>;
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
@ -32,7 +35,7 @@ describe('RevisionsService', () => {
RevisionsService, RevisionsService,
{ {
provide: getRepositoryToken(Revision), provide: getRepositoryToken(Revision),
useValue: {}, useClass: Repository,
}, },
], ],
imports: [ imports: [
@ -57,7 +60,7 @@ describe('RevisionsService', () => {
.overrideProvider(getRepositoryToken(Note)) .overrideProvider(getRepositoryToken(Note))
.useValue({}) .useValue({})
.overrideProvider(getRepositoryToken(Revision)) .overrideProvider(getRepositoryToken(Revision))
.useValue({}) .useClass(Repository)
.overrideProvider(getRepositoryToken(Tag)) .overrideProvider(getRepositoryToken(Tag))
.useValue({}) .useValue({})
.overrideProvider(getRepositoryToken(NoteGroupPermission)) .overrideProvider(getRepositoryToken(NoteGroupPermission))
@ -69,9 +72,26 @@ describe('RevisionsService', () => {
.compile(); .compile();
service = module.get<RevisionsService>(RevisionsService); service = module.get<RevisionsService>(RevisionsService);
revisionRepo = module.get<Repository<Revision>>(
getRepositoryToken(Revision),
);
}); });
it('should be defined', () => { it('should be defined', () => {
expect(service).toBeDefined(); expect(service).toBeDefined();
}); });
describe('getRevision', () => {
it('returns a revision', async () => {
const revision = Revision.create('', '');
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(revision);
expect(await service.getRevision({} as Note, 1)).toEqual(revision);
});
it('throws if the revision is not in the databse', async () => {
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(undefined);
await expect(service.getRevision({} as Note, 1)).rejects.toThrow(
NotInDBError,
);
});
});
}); });

View file

@ -13,6 +13,7 @@ import { RevisionMetadataDto } from './revision-metadata.dto';
import { RevisionDto } from './revision.dto'; import { RevisionDto } from './revision.dto';
import { Revision } from './revision.entity'; import { Revision } from './revision.entity';
import { Note } from '../notes/note.entity'; import { Note } from '../notes/note.entity';
import { NotInDBError } from '../errors/errors';
@Injectable() @Injectable()
export class RevisionsService { export class RevisionsService {
@ -34,16 +35,22 @@ export class RevisionsService {
} }
async getRevision(note: Note, revisionId: number): Promise<Revision> { async getRevision(note: Note, revisionId: number): Promise<Revision> {
return await this.revisionRepository.findOne({ const revision = await this.revisionRepository.findOne({
where: { where: {
id: revisionId, id: revisionId,
note: note, note: note,
}, },
}); });
if (revision === undefined) {
throw new NotInDBError(
`Revision with ID ${revisionId} for note ${note.id} not found.`,
);
}
return revision;
} }
async getLatestRevision(noteId: string): Promise<Revision> { async getLatestRevision(noteId: string): Promise<Revision> {
return await this.revisionRepository.findOne({ const revision = await this.revisionRepository.findOne({
where: { where: {
note: noteId, note: noteId,
}, },
@ -52,10 +59,14 @@ export class RevisionsService {
id: 'DESC', id: 'DESC',
}, },
}); });
if (revision === undefined) {
throw new NotInDBError(`Revision for note ${noteId} not found.`);
}
return revision;
} }
async getFirstRevision(noteId: string): Promise<Revision> { async getFirstRevision(noteId: string): Promise<Revision> {
return await this.revisionRepository.findOne({ const revision = await this.revisionRepository.findOne({
where: { where: {
note: noteId, note: noteId,
}, },
@ -63,6 +74,10 @@ export class RevisionsService {
createdAt: 'ASC', createdAt: 'ASC',
}, },
}); });
if (revision === undefined) {
throw new NotInDBError(`Revision for note ${noteId} not found.`);
}
return revision;
} }
toRevisionMetadataDto(revision: Revision): RevisionMetadataDto { toRevisionMetadataDto(revision: Revision): RevisionMetadataDto {