mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
DIRTY: Mock Repository
Signed-off-by: Yannick Bungers <git@innay.de>
This commit is contained in:
parent
2250495d4f
commit
9263d4468a
2 changed files with 324 additions and 18 deletions
|
@ -9,7 +9,13 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getDataSourceToken, getRepositoryToken } from '@nestjs/typeorm';
|
import { getDataSourceToken, getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { DataSource, EntityManager, Repository } from 'typeorm';
|
import {
|
||||||
|
DataSource,
|
||||||
|
EntityManager,
|
||||||
|
EntityTarget,
|
||||||
|
Repository,
|
||||||
|
SelectQueryBuilder,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
import { Author } from '../authors/author.entity';
|
import { Author } from '../authors/author.entity';
|
||||||
|
@ -38,6 +44,8 @@ import { HistoryEntryImportDto } from './history-entry-import.dto';
|
||||||
import { HistoryEntry } from './history-entry.entity';
|
import { HistoryEntry } from './history-entry.entity';
|
||||||
import { HistoryService } from './history.service';
|
import { HistoryService } from './history.service';
|
||||||
|
|
||||||
|
import Any = jasmine.Any;
|
||||||
|
|
||||||
describe('HistoryService', () => {
|
describe('HistoryService', () => {
|
||||||
let service: HistoryService;
|
let service: HistoryService;
|
||||||
let historyRepo: Repository<HistoryEntry>;
|
let historyRepo: Repository<HistoryEntry>;
|
||||||
|
@ -47,16 +55,17 @@ describe('HistoryService', () => {
|
||||||
[(entityManager: EntityManager) => Promise<void>]
|
[(entityManager: EntityManager) => Promise<void>]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
class CreateQueryBuilderClass {
|
class CreateQueryBuilderClass<Entity> {
|
||||||
leftJoinAndSelect: () => CreateQueryBuilderClass;
|
leftJoinAndSelect: () => CreateQueryBuilderClass<Entity>;
|
||||||
where: () => CreateQueryBuilderClass;
|
where: () => CreateQueryBuilderClass<Entity>;
|
||||||
orWhere: () => CreateQueryBuilderClass;
|
orWhere: () => CreateQueryBuilderClass<Entity>;
|
||||||
setParameter: () => CreateQueryBuilderClass;
|
setParameter: () => CreateQueryBuilderClass<Entity>;
|
||||||
getOne: () => HistoryEntry;
|
getOne: () => Entity;
|
||||||
getMany: () => HistoryEntry[];
|
getMany: () => Entity[];
|
||||||
}
|
}
|
||||||
|
|
||||||
let createQueryBuilderFunc: CreateQueryBuilderClass;
|
let createQueryBuilderFunc: CreateQueryBuilderClass<HistoryEntry>;
|
||||||
|
let createQueryBuilderFuncNote: CreateQueryBuilderClass<Note>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
noteRepo = new Repository<Note>(
|
noteRepo = new Repository<Note>(
|
||||||
|
@ -148,12 +157,29 @@ describe('HistoryService', () => {
|
||||||
getOne: () => historyEntry,
|
getOne: () => historyEntry,
|
||||||
getMany: () => [historyEntry],
|
getMany: () => [historyEntry],
|
||||||
};
|
};
|
||||||
createQueryBuilderFunc = createQueryBuilder as CreateQueryBuilderClass;
|
createQueryBuilderFunc =
|
||||||
|
createQueryBuilder as CreateQueryBuilderClass<HistoryEntry>;
|
||||||
|
const note = Note.create(null);
|
||||||
jest
|
jest
|
||||||
.spyOn(historyRepo, 'createQueryBuilder')
|
.spyOn(historyRepo, 'createQueryBuilder')
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.mockImplementation(() => createQueryBuilder);
|
.mockImplementation(() => createQueryBuilder);
|
||||||
|
const createQueryBuilderNote = {
|
||||||
|
leftJoinAndSelect: () => createQueryBuilderNote,
|
||||||
|
where: () => createQueryBuilderNote,
|
||||||
|
orWhere: () => createQueryBuilderNote,
|
||||||
|
setParameter: () => createQueryBuilderNote,
|
||||||
|
getOne: () => note,
|
||||||
|
getMany: () => [note],
|
||||||
|
};
|
||||||
|
createQueryBuilderFuncNote =
|
||||||
|
createQueryBuilderNote as CreateQueryBuilderClass<Note>;
|
||||||
|
jest
|
||||||
|
.spyOn(historyRepo, 'createQueryBuilder')
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
.mockImplementation(() => createQueryBuilderNote);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
|
@ -388,16 +414,41 @@ describe('HistoryService', () => {
|
||||||
updatedAt: historyEntryImport.lastVisitedAt,
|
updatedAt: historyEntryImport.lastVisitedAt,
|
||||||
};
|
};
|
||||||
|
|
||||||
const createQueryBuilder = mockSelectQueryBuilderInRepo(noteRepo, note);
|
function createQueryBuilder(entityClass: any): SelectQueryBuilder<any> {
|
||||||
|
if (entityClass.name == 'HistoryEntry') {
|
||||||
|
return mockSelectQueryBuilderInRepo(
|
||||||
|
historyRepo,
|
||||||
|
newlyCreatedHistoryEntry,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return mockSelectQueryBuilderInRepo(noteRepo, note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
class QueryBuilderExtension<Entity> extends SelectQueryBuilder<Entity>{
|
||||||
|
createQueryBuilder(): this {
|
||||||
|
if (Entity.toString() == 'HistoryEntry') {
|
||||||
|
return mockSelectQueryBuilderInRepo(
|
||||||
|
historyRepo,
|
||||||
|
newlyCreatedHistoryEntry,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return mockSelectQueryBuilderInRepo(noteRepo, note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const mockedManager = Mock.of<EntityManager>({
|
const mockedManager = Mock.of<EntityManager>({
|
||||||
find: jest.fn().mockResolvedValueOnce([historyEntry]),
|
find: jest.fn().mockResolvedValueOnce([historyEntry]),
|
||||||
createQueryBuilder: () => createQueryBuilder,
|
remove: jest
|
||||||
remove: jest.fn().mockImplementationOnce(async (_: HistoryEntry) => {
|
.fn()
|
||||||
// TODO: reimplement checks below
|
.mockImplementationOnce(async (entry: HistoryEntry) => {
|
||||||
//expect(await (await entry.note).aliases).toHaveLength(1);
|
expect(await (await entry.note).aliases).toHaveLength(1);
|
||||||
//expect((await (await entry.note).aliases)[0].name).toEqual(alias);
|
expect((await (await entry.note).aliases)[0].name).toEqual(alias);
|
||||||
//expect(entry.pinStatus).toEqual(false);
|
expect(entry.pinStatus).toEqual(true);
|
||||||
}),
|
}),
|
||||||
|
createQueryBuilder: jest.fn(),
|
||||||
save: jest.fn().mockImplementationOnce(async (entry: HistoryEntry) => {
|
save: jest.fn().mockImplementationOnce(async (entry: HistoryEntry) => {
|
||||||
expect((await entry.note).aliases).toEqual(
|
expect((await entry.note).aliases).toEqual(
|
||||||
(await newlyCreatedHistoryEntry.note).aliases,
|
(await newlyCreatedHistoryEntry.note).aliases,
|
||||||
|
@ -406,6 +457,11 @@ describe('HistoryService', () => {
|
||||||
expect(entry.updatedAt).toEqual(newlyCreatedHistoryEntry.updatedAt);
|
expect(entry.updatedAt).toEqual(newlyCreatedHistoryEntry.updatedAt);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
jest
|
||||||
|
.spyOn(mockedManager, 'createQueryBuilder')
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
.mockImplementation((type) => createQueryBuilder(type));
|
||||||
mockedTransaction.mockImplementation((cb) => cb(mockedManager));
|
mockedTransaction.mockImplementation((cb) => cb(mockedManager));
|
||||||
await service.setHistory(user, [historyEntryImport]);
|
await service.setHistory(user, [historyEntryImport]);
|
||||||
});
|
});
|
||||||
|
|
250
backend/src/utils/test-utils/mockRepository.ts
Normal file
250
backend/src/utils/test-utils/mockRepository.ts
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
import {
|
||||||
|
DeepPartial,
|
||||||
|
DeleteResult,
|
||||||
|
EntityManager,
|
||||||
|
EntityTarget,
|
||||||
|
FindManyOptions,
|
||||||
|
FindOptionsWhere,
|
||||||
|
InsertResult,
|
||||||
|
ObjectID,
|
||||||
|
QueryRunner,
|
||||||
|
RemoveOptions,
|
||||||
|
Repository,
|
||||||
|
SaveOptions,
|
||||||
|
SelectQueryBuilder,
|
||||||
|
UpdateResult,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
|
||||||
|
import { UpsertOptions } from 'typeorm/repository/UpsertOptions';
|
||||||
|
|
||||||
|
class MockRepository<T> implements Repository<T> {
|
||||||
|
|
||||||
|
entities: T[]
|
||||||
|
|
||||||
|
createQueryBuilder(
|
||||||
|
alias?: string,
|
||||||
|
queryRunner?: QueryRunner,
|
||||||
|
): SelectQueryBuilder<T> {
|
||||||
|
new SelectQueryBuilder()
|
||||||
|
//return super.createQueryBuilder(alias, queryRunner);
|
||||||
|
}
|
||||||
|
find(options?: FindManyOptions<T>): Promise<T[]> {
|
||||||
|
//return super.find(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(): Promise<void> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
count(options: FindManyOptions<T> | undefined): Promise<number> {
|
||||||
|
return Promise.resolve(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
countBy(where: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number> {
|
||||||
|
return Promise.resolve(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
create(): T {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrement(
|
||||||
|
conditions: FindOptionsWhere<T>,
|
||||||
|
propertyPath: string,
|
||||||
|
value: number | string,
|
||||||
|
): Promise<UpdateResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(
|
||||||
|
criteria:
|
||||||
|
| string
|
||||||
|
| string[]
|
||||||
|
| number
|
||||||
|
| number[]
|
||||||
|
| Date
|
||||||
|
| Date[]
|
||||||
|
| ObjectID
|
||||||
|
| ObjectID[]
|
||||||
|
| FindOptionsWhere<T>,
|
||||||
|
): Promise<DeleteResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
extend<CustomRepository>(
|
||||||
|
custom: CustomRepository & ThisType<Repository<T> & CustomRepository>,
|
||||||
|
): Repository<T> & CustomRepository {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
findAndCount(
|
||||||
|
options: FindManyOptions<T> | undefined,
|
||||||
|
): Promise<[T[], number]> {
|
||||||
|
return Promise.resolve([[], 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
findAndCountBy(
|
||||||
|
where: FindOptionsWhere<T> | FindOptionsWhere<T>[],
|
||||||
|
): Promise<[T[], number]> {
|
||||||
|
return Promise.resolve([[], 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
findBy(where: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<T[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
findByIds(ids: any[]): Promise<T[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
findOne(options: FindOneOptions<T>): Promise<T | null> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
findOneBy(
|
||||||
|
where: FindOptionsWhere<T> | FindOptionsWhere<T>[],
|
||||||
|
): Promise<T | null> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
findOneById(id: number | string | Date | ObjectID): Promise<T | null> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
findOneByOrFail(
|
||||||
|
where: FindOptionsWhere<T> | FindOptionsWhere<T>[],
|
||||||
|
): Promise<T> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
findOneOrFail(options: FindOneOptions<T>): Promise<T> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
getId(entity: T): any {}
|
||||||
|
|
||||||
|
hasId(entity: T): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
increment(
|
||||||
|
conditions: FindOptionsWhere<T>,
|
||||||
|
propertyPath: string,
|
||||||
|
value: number | string,
|
||||||
|
): Promise<UpdateResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(
|
||||||
|
entity: QueryDeepPartialEntity<T> | QueryDeepPartialEntity<T>[],
|
||||||
|
): Promise<InsertResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly manager: EntityManager;
|
||||||
|
|
||||||
|
merge(mergeIntoEntity: T, entityLikes: DeepPartial<T>): T {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
get metadata(): import('..').EntityMetadata {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
preload(entityLike: DeepPartial<T>): Promise<T | undefined> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
query(query: string, parameters: any[] | undefined): Promise<any> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly queryRunner: QueryRunner;
|
||||||
|
|
||||||
|
recover<T>(
|
||||||
|
entities: T[],
|
||||||
|
options: SaveOptions & { reload: false },
|
||||||
|
): Promise<T[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(entities: T[], options: RemoveOptions | undefined): Promise<T[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
restore(
|
||||||
|
criteria:
|
||||||
|
| string
|
||||||
|
| string[]
|
||||||
|
| number
|
||||||
|
| number[]
|
||||||
|
| Date
|
||||||
|
| Date[]
|
||||||
|
| ObjectID
|
||||||
|
| ObjectID[]
|
||||||
|
| FindOptionsWhere<T>,
|
||||||
|
): Promise<UpdateResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
save<T>(
|
||||||
|
entities: T[],
|
||||||
|
options: SaveOptions & { reload: false },
|
||||||
|
): Promise<T[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
softDelete(
|
||||||
|
criteria:
|
||||||
|
| string
|
||||||
|
| string[]
|
||||||
|
| number
|
||||||
|
| number[]
|
||||||
|
| Date
|
||||||
|
| Date[]
|
||||||
|
| ObjectID
|
||||||
|
| ObjectID[]
|
||||||
|
| FindOptionsWhere<T>,
|
||||||
|
): Promise<UpdateResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
softRemove<T>(
|
||||||
|
entities: T[],
|
||||||
|
options: SaveOptions & { reload: false },
|
||||||
|
): Promise<T[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly target: EntityTarget<T>;
|
||||||
|
|
||||||
|
update(
|
||||||
|
criteria:
|
||||||
|
| string
|
||||||
|
| string[]
|
||||||
|
| number
|
||||||
|
| number[]
|
||||||
|
| Date
|
||||||
|
| Date[]
|
||||||
|
| ObjectID
|
||||||
|
| ObjectID[]
|
||||||
|
| FindOptionsWhere<T>,
|
||||||
|
partialEntity: QueryDeepPartialEntity<T>,
|
||||||
|
): Promise<UpdateResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
upsert(
|
||||||
|
entityOrEntities: QueryDeepPartialEntity<T> | QueryDeepPartialEntity<T>[],
|
||||||
|
conflictPathsOrOptions: string[] | UpsertOptions<T>,
|
||||||
|
): Promise<InsertResult> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
Loading…
Reference in a new issue