mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-24 18:56:32 -05:00
fix: improve and adjust tests
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
eb986b1504
commit
bb355feddc
4 changed files with 490 additions and 342 deletions
|
@ -30,6 +30,8 @@ import { NoteGroupPermission } from '../permissions/note-group-permission.entity
|
||||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||||
import { Edit } from '../revisions/edit.entity';
|
import { Edit } from '../revisions/edit.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
|
import { RevisionsModule } from '../revisions/revisions.module';
|
||||||
|
import { RevisionsService } from '../revisions/revisions.service';
|
||||||
import { Session } from '../users/session.entity';
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
|
@ -40,6 +42,7 @@ import { HistoryService } from './history.service';
|
||||||
|
|
||||||
describe('HistoryService', () => {
|
describe('HistoryService', () => {
|
||||||
let service: HistoryService;
|
let service: HistoryService;
|
||||||
|
let revisionsService: RevisionsService;
|
||||||
let historyRepo: Repository<HistoryEntry>;
|
let historyRepo: Repository<HistoryEntry>;
|
||||||
let noteRepo: Repository<Note>;
|
let noteRepo: Repository<Note>;
|
||||||
let mockedTransaction: jest.Mock<
|
let mockedTransaction: jest.Mock<
|
||||||
|
@ -94,6 +97,7 @@ describe('HistoryService', () => {
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
NotesModule,
|
NotesModule,
|
||||||
|
RevisionsModule,
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [
|
load: [
|
||||||
|
@ -135,6 +139,7 @@ describe('HistoryService', () => {
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
service = module.get<HistoryService>(HistoryService);
|
service = module.get<HistoryService>(HistoryService);
|
||||||
|
revisionsService = module.get<RevisionsService>(RevisionsService);
|
||||||
historyRepo = module.get<Repository<HistoryEntry>>(
|
historyRepo = module.get<Repository<HistoryEntry>>(
|
||||||
getRepositoryToken(HistoryEntry),
|
getRepositoryToken(HistoryEntry),
|
||||||
);
|
);
|
||||||
|
@ -419,8 +424,17 @@ describe('HistoryService', () => {
|
||||||
const title = 'title';
|
const title = 'title';
|
||||||
const tags = ['tag1', 'tag2'];
|
const tags = ['tag1', 'tag2'];
|
||||||
const note = Note.create(user, alias) as Note;
|
const note = Note.create(user, alias) as Note;
|
||||||
note.title = title;
|
const revision = Revision.create(
|
||||||
note.tags = Promise.resolve(
|
'',
|
||||||
|
'',
|
||||||
|
note,
|
||||||
|
null,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
[],
|
||||||
|
) as Revision;
|
||||||
|
revision.title = title;
|
||||||
|
revision.tags = Promise.resolve(
|
||||||
tags.map((tag) => {
|
tags.map((tag) => {
|
||||||
const newTag = new Tag();
|
const newTag = new Tag();
|
||||||
newTag.name = tag;
|
newTag.name = tag;
|
||||||
|
@ -431,6 +445,13 @@ describe('HistoryService', () => {
|
||||||
historyEntry.pinStatus = true;
|
historyEntry.pinStatus = true;
|
||||||
|
|
||||||
mockSelectQueryBuilderInRepo(noteRepo, note);
|
mockSelectQueryBuilderInRepo(noteRepo, note);
|
||||||
|
jest
|
||||||
|
.spyOn(revisionsService, 'getLatestRevision')
|
||||||
|
.mockImplementation((requestedNote) => {
|
||||||
|
expect(note).toBe(requestedNote);
|
||||||
|
return Promise.resolve(revision);
|
||||||
|
});
|
||||||
|
|
||||||
const historyEntryDto = await service.toHistoryEntryDto(historyEntry);
|
const historyEntryDto = await service.toHistoryEntryDto(historyEntry);
|
||||||
expect(historyEntryDto.pinStatus).toEqual(true);
|
expect(historyEntryDto.pinStatus).toEqual(true);
|
||||||
expect(historyEntryDto.identifier).toEqual(alias);
|
expect(historyEntryDto.identifier).toEqual(alias);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { EventEmitterModule } from '@nestjs/event-emitter';
|
import { EventEmitterModule } from '@nestjs/event-emitter';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
import { Mock } from 'ts-mockery';
|
||||||
import { DataSource, EntityManager, Repository } from 'typeorm';
|
import { DataSource, EntityManager, Repository } from 'typeorm';
|
||||||
|
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
|
@ -35,6 +36,7 @@ import { RevisionsModule } from '../revisions/revisions.module';
|
||||||
import { Session } from '../users/session.entity';
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
|
import { mockSelectQueryBuilderInRepo } from '../utils/test-utils/mockSelectQueryBuilder';
|
||||||
import { Alias } from './alias.entity';
|
import { Alias } from './alias.entity';
|
||||||
import { AliasService } from './alias.service';
|
import { AliasService } from './alias.service';
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
|
@ -259,15 +261,13 @@ describe('AliasService', () => {
|
||||||
.spyOn(aliasRepo, 'save')
|
.spyOn(aliasRepo, 'save')
|
||||||
.mockImplementationOnce(async (alias: Alias): Promise<Alias> => alias)
|
.mockImplementationOnce(async (alias: Alias): Promise<Alias> => alias)
|
||||||
.mockImplementationOnce(async (alias: Alias): Promise<Alias> => alias);
|
.mockImplementationOnce(async (alias: Alias): Promise<Alias> => alias);
|
||||||
const createQueryBuilder = {
|
|
||||||
leftJoinAndSelect: () => createQueryBuilder,
|
mockSelectQueryBuilderInRepo(
|
||||||
where: () => createQueryBuilder,
|
noteRepo,
|
||||||
orWhere: () => createQueryBuilder,
|
Mock.of<Note>({
|
||||||
setParameter: () => createQueryBuilder,
|
...note,
|
||||||
getOne: async () => {
|
aliases: Promise.resolve(
|
||||||
return {
|
(await note.aliases).map((anAlias) => {
|
||||||
...note,
|
|
||||||
aliases: (await note.aliases).map((anAlias) => {
|
|
||||||
if (anAlias.primary) {
|
if (anAlias.primary) {
|
||||||
anAlias.primary = false;
|
anAlias.primary = false;
|
||||||
}
|
}
|
||||||
|
@ -276,14 +276,10 @@ describe('AliasService', () => {
|
||||||
}
|
}
|
||||||
return anAlias;
|
return anAlias;
|
||||||
}),
|
}),
|
||||||
};
|
),
|
||||||
},
|
}),
|
||||||
};
|
);
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
const savedAlias = await service.makeAliasPrimary(note, alias2.name);
|
const savedAlias = await service.makeAliasPrimary(note, alias2.name);
|
||||||
expect(savedAlias.name).toEqual(alias2.name);
|
expect(savedAlias.name).toEqual(alias2.name);
|
||||||
expect(savedAlias.primary).toBeTruthy();
|
expect(savedAlias.primary).toBeTruthy();
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
|
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
import { Mock } from 'ts-mockery';
|
||||||
import {
|
import {
|
||||||
DataSource,
|
DataSource,
|
||||||
EntityManager,
|
EntityManager,
|
||||||
|
@ -43,20 +44,24 @@ import { RealtimeNoteModule } from '../realtime/realtime-note/realtime-note.modu
|
||||||
import { Edit } from '../revisions/edit.entity';
|
import { Edit } from '../revisions/edit.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { RevisionsModule } from '../revisions/revisions.module';
|
import { RevisionsModule } from '../revisions/revisions.module';
|
||||||
|
import { RevisionsService } from '../revisions/revisions.service';
|
||||||
import { Session } from '../users/session.entity';
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
|
import { mockSelectQueryBuilderInRepo } from '../utils/test-utils/mockSelectQueryBuilder';
|
||||||
import { Alias } from './alias.entity';
|
import { Alias } from './alias.entity';
|
||||||
import { AliasService } from './alias.service';
|
import { AliasService } from './alias.service';
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
import { NotesService } from './notes.service';
|
import { NotesService } from './notes.service';
|
||||||
import { Tag } from './tag.entity';
|
import { Tag } from './tag.entity';
|
||||||
|
|
||||||
|
jest.mock('../revisions/revisions.service');
|
||||||
|
|
||||||
describe('NotesService', () => {
|
describe('NotesService', () => {
|
||||||
let service: NotesService;
|
let service: NotesService;
|
||||||
|
let revisionsService: RevisionsService;
|
||||||
const noteMockConfig: NoteConfig = createDefaultMockNoteConfig();
|
const noteMockConfig: NoteConfig = createDefaultMockNoteConfig();
|
||||||
let noteRepo: Repository<Note>;
|
let noteRepo: Repository<Note>;
|
||||||
let revisionRepo: Repository<Revision>;
|
|
||||||
let userRepo: Repository<User>;
|
let userRepo: Repository<User>;
|
||||||
let groupRepo: Repository<Group>;
|
let groupRepo: Repository<Group>;
|
||||||
let forbiddenNoteId: string;
|
let forbiddenNoteId: string;
|
||||||
|
@ -74,99 +79,10 @@ describe('NotesService', () => {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Note and a corresponding User and Group for testing.
|
|
||||||
* The Note does not have any aliases.
|
|
||||||
*/
|
|
||||||
async function getMockData(): Promise<[Note, User, Group]> {
|
|
||||||
const user = User.create('hardcoded', 'Testy') as User;
|
|
||||||
const author = Author.create(1);
|
|
||||||
author.user = Promise.resolve(user);
|
|
||||||
const group = Group.create('testGroup', 'testGroup', false) as Group;
|
|
||||||
const content = 'testContent';
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(async (note: Note): Promise<Note> => note);
|
|
||||||
mockGroupRepo();
|
|
||||||
const note = await service.createNote(content, null);
|
|
||||||
const revisions = await note.revisions;
|
|
||||||
revisions[0].edits = Promise.resolve([
|
|
||||||
{
|
|
||||||
revisions: Promise.resolve(revisions),
|
|
||||||
startPos: 0,
|
|
||||||
endPos: 1,
|
|
||||||
updatedAt: new Date(1549312452000),
|
|
||||||
author: Promise.resolve(author),
|
|
||||||
} as Edit,
|
|
||||||
{
|
|
||||||
revisions: Promise.resolve(revisions),
|
|
||||||
startPos: 0,
|
|
||||||
endPos: 1,
|
|
||||||
updatedAt: new Date(1549312452001),
|
|
||||||
author: Promise.resolve(author),
|
|
||||||
} as Edit,
|
|
||||||
]);
|
|
||||||
revisions[0].createdAt = new Date(1549312452000);
|
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValue(revisions[0]);
|
|
||||||
const createQueryBuilder = {
|
|
||||||
innerJoin: () => createQueryBuilder,
|
|
||||||
where: () => createQueryBuilder,
|
|
||||||
getMany: () => [user],
|
|
||||||
};
|
|
||||||
jest
|
|
||||||
.spyOn(userRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
note.publicId = 'testId';
|
|
||||||
note.title = 'testTitle';
|
|
||||||
note.description = 'testDescription';
|
|
||||||
note.owner = Promise.resolve(user);
|
|
||||||
note.userPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
note: Promise.resolve(note),
|
|
||||||
user: Promise.resolve(user),
|
|
||||||
canEdit: true,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
note.groupPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
note: Promise.resolve(note),
|
|
||||||
group: Promise.resolve(group),
|
|
||||||
canEdit: true,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
note.tags = Promise.resolve([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'testTag',
|
|
||||||
notes: Promise.resolve([note]),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
note.viewCount = 1337;
|
|
||||||
|
|
||||||
return [note, user, group];
|
|
||||||
}
|
|
||||||
|
|
||||||
function mockGroupRepo() {
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockReset();
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockImplementation((args) => {
|
|
||||||
const groupName = (args.where as FindOptionsWhere<Group>).name;
|
|
||||||
if (groupName === loggedin.name) {
|
|
||||||
return Promise.resolve(loggedin as Group);
|
|
||||||
} else if (groupName === everyone.name) {
|
|
||||||
return Promise.resolve(everyone as Group);
|
|
||||||
} else {
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
jest.resetModules();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We need to have *one* userRepo for both the providers array and
|
* We need to have *one* userRepo for both the providers array and
|
||||||
* the overrideProvider call, as otherwise we have two instances
|
* the overrideProvider call, as otherwise we have two instances
|
||||||
|
@ -202,9 +118,19 @@ describe('NotesService', () => {
|
||||||
),
|
),
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
revisionsService = Mock.of<RevisionsService>({
|
||||||
|
getLatestRevision: jest.fn(),
|
||||||
|
createRevision: jest.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
NotesService,
|
NotesService,
|
||||||
|
{
|
||||||
|
provide: RevisionsService,
|
||||||
|
useValue: revisionsService,
|
||||||
|
},
|
||||||
AliasService,
|
AliasService,
|
||||||
{
|
{
|
||||||
provide: getRepositoryToken(Note),
|
provide: getRepositoryToken(Note),
|
||||||
|
@ -214,6 +140,10 @@ describe('NotesService', () => {
|
||||||
provide: getRepositoryToken(Tag),
|
provide: getRepositoryToken(Tag),
|
||||||
useClass: Repository,
|
useClass: Repository,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(Revision),
|
||||||
|
useClass: Repository,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: getRepositoryToken(Alias),
|
provide: getRepositoryToken(Alias),
|
||||||
useClass: Repository,
|
useClass: Repository,
|
||||||
|
@ -280,12 +210,106 @@ describe('NotesService', () => {
|
||||||
loggedinDefaultAccessPermission = noteConfig.permissions.default.loggedIn;
|
loggedinDefaultAccessPermission = noteConfig.permissions.default.loggedIn;
|
||||||
service = module.get<NotesService>(NotesService);
|
service = module.get<NotesService>(NotesService);
|
||||||
noteRepo = module.get<Repository<Note>>(getRepositoryToken(Note));
|
noteRepo = module.get<Repository<Note>>(getRepositoryToken(Note));
|
||||||
revisionRepo = module.get<Repository<Revision>>(
|
|
||||||
getRepositoryToken(Revision),
|
|
||||||
);
|
|
||||||
eventEmitter = module.get<EventEmitter2>(EventEmitter2);
|
eventEmitter = module.get<EventEmitter2>(EventEmitter2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Note and a corresponding User and Group for testing.
|
||||||
|
* The Note does not have any aliases.
|
||||||
|
*/
|
||||||
|
async function getMockData(): Promise<[Note, User, Group, Revision]> {
|
||||||
|
const user = User.create('hardcoded', 'Testy') as User;
|
||||||
|
const author = Author.create(1);
|
||||||
|
author.user = Promise.resolve(user);
|
||||||
|
const group = Group.create('testGroup', 'testGroup', false) as Group;
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
.mockImplementation(async (note: Note): Promise<Note> => note);
|
||||||
|
mockGroupRepo();
|
||||||
|
|
||||||
|
const revision = Mock.of<Revision>({
|
||||||
|
edits: Promise.resolve([
|
||||||
|
{
|
||||||
|
startPos: 0,
|
||||||
|
endPos: 1,
|
||||||
|
updatedAt: new Date(1549312452000),
|
||||||
|
author: Promise.resolve(author),
|
||||||
|
} as Edit,
|
||||||
|
{
|
||||||
|
startPos: 0,
|
||||||
|
endPos: 1,
|
||||||
|
updatedAt: new Date(1549312452001),
|
||||||
|
author: Promise.resolve(author),
|
||||||
|
} as Edit,
|
||||||
|
]),
|
||||||
|
createdAt: new Date(1549312452000),
|
||||||
|
tags: Promise.resolve([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: 'tag1',
|
||||||
|
} as Tag,
|
||||||
|
]),
|
||||||
|
content: 'mockContent',
|
||||||
|
description: 'mockDescription',
|
||||||
|
title: 'mockTitle',
|
||||||
|
});
|
||||||
|
|
||||||
|
const note = Mock.of<Note>({
|
||||||
|
revisions: Promise.resolve([revision]),
|
||||||
|
aliases: Promise.resolve([]),
|
||||||
|
});
|
||||||
|
|
||||||
|
mockRevisionService(note, revision);
|
||||||
|
|
||||||
|
mockSelectQueryBuilderInRepo(userRepo, user);
|
||||||
|
note.publicId = 'testId';
|
||||||
|
note.owner = Promise.resolve(user);
|
||||||
|
note.userPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
note: Promise.resolve(note),
|
||||||
|
user: Promise.resolve(user),
|
||||||
|
canEdit: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
note.groupPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
note: Promise.resolve(note),
|
||||||
|
group: Promise.resolve(group),
|
||||||
|
canEdit: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
note.viewCount = 1337;
|
||||||
|
|
||||||
|
return [note, user, group, revision];
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockRevisionService(note: Note, revision: Revision) {
|
||||||
|
jest
|
||||||
|
.spyOn(revisionsService, 'getLatestRevision')
|
||||||
|
.mockImplementation((requestedNote) => {
|
||||||
|
expect(requestedNote).toBe(note);
|
||||||
|
return Promise.resolve(revision);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockGroupRepo() {
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockReset();
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockImplementation((args) => {
|
||||||
|
const groupName = (args.where as FindOptionsWhere<Group>).name;
|
||||||
|
if (groupName === loggedin.name) {
|
||||||
|
return Promise.resolve(loggedin as Group);
|
||||||
|
} else if (groupName === everyone.name) {
|
||||||
|
return Promise.resolve(everyone as Group);
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
expect(service).toBeDefined();
|
expect(service).toBeDefined();
|
||||||
});
|
});
|
||||||
|
@ -297,52 +321,19 @@ describe('NotesService', () => {
|
||||||
const note = Note.create(user, alias) as Note;
|
const note = Note.create(user, alias) as Note;
|
||||||
|
|
||||||
it('with no note', async () => {
|
it('with no note', async () => {
|
||||||
const createQueryBuilder = {
|
mockSelectQueryBuilderInRepo(noteRepo, null);
|
||||||
leftJoinAndSelect: () => createQueryBuilder,
|
|
||||||
where: () => createQueryBuilder,
|
|
||||||
getMany: async () => {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
const notes = await service.getUserNotes(user);
|
const notes = await service.getUserNotes(user);
|
||||||
expect(notes).toEqual([]);
|
expect(notes).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with one note', async () => {
|
it('with one note', async () => {
|
||||||
const createQueryBuilder = {
|
mockSelectQueryBuilderInRepo(noteRepo, note);
|
||||||
leftJoinAndSelect: () => createQueryBuilder,
|
|
||||||
where: () => createQueryBuilder,
|
|
||||||
getMany: async () => {
|
|
||||||
return [note];
|
|
||||||
},
|
|
||||||
};
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
const notes = await service.getUserNotes(user);
|
const notes = await service.getUserNotes(user);
|
||||||
expect(notes).toEqual([note]);
|
expect(notes).toEqual([note]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with multiple note', async () => {
|
it('with multiple note', async () => {
|
||||||
const createQueryBuilder = {
|
mockSelectQueryBuilderInRepo(noteRepo, [note, note]);
|
||||||
leftJoinAndSelect: () => createQueryBuilder,
|
|
||||||
where: () => createQueryBuilder,
|
|
||||||
getMany: async () => {
|
|
||||||
return [note, note];
|
|
||||||
},
|
|
||||||
};
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
const notes = await service.getUserNotes(user);
|
const notes = await service.getUserNotes(user);
|
||||||
expect(notes).toEqual([note, note]);
|
expect(notes).toEqual([note, note]);
|
||||||
});
|
});
|
||||||
|
@ -353,6 +344,9 @@ describe('NotesService', () => {
|
||||||
const user = User.create('hardcoded', 'Testy') as User;
|
const user = User.create('hardcoded', 'Testy') as User;
|
||||||
const alias = 'alias';
|
const alias = 'alias';
|
||||||
const content = 'testContent';
|
const content = 'testContent';
|
||||||
|
const newRevision = Mock.of<Revision>({});
|
||||||
|
let createRevisionSpy: jest.SpyInstance;
|
||||||
|
|
||||||
describe('works', () => {
|
describe('works', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest
|
jest
|
||||||
|
@ -361,12 +355,16 @@ describe('NotesService', () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.mockImplementation(async (note: Note): Promise<Note> => note);
|
.mockImplementation(async (note: Note): Promise<Note> => note);
|
||||||
mockGroupRepo();
|
mockGroupRepo();
|
||||||
|
|
||||||
|
createRevisionSpy = jest
|
||||||
|
.spyOn(revisionsService, 'createRevision')
|
||||||
|
.mockResolvedValue(newRevision);
|
||||||
});
|
});
|
||||||
it('without alias, without owner', async () => {
|
it('without alias, without owner', async () => {
|
||||||
const newNote = await service.createNote(content, null);
|
const newNote = await service.createNote(content, null);
|
||||||
const revisions = await newNote.revisions;
|
|
||||||
expect(revisions).toHaveLength(1);
|
expect(createRevisionSpy).toHaveBeenCalledWith(newNote, content);
|
||||||
expect(revisions[0].content).toEqual(content);
|
expect(await newNote.revisions).toStrictEqual([newRevision]);
|
||||||
expect(await newNote.historyEntries).toHaveLength(0);
|
expect(await newNote.historyEntries).toHaveLength(0);
|
||||||
expect(await newNote.userPermissions).toHaveLength(0);
|
expect(await newNote.userPermissions).toHaveLength(0);
|
||||||
const groupPermissions = await newNote.groupPermissions;
|
const groupPermissions = await newNote.groupPermissions;
|
||||||
|
@ -383,15 +381,13 @@ describe('NotesService', () => {
|
||||||
expect((await groupPermissions[1].group).name).toEqual(
|
expect((await groupPermissions[1].group).name).toEqual(
|
||||||
SpecialGroup.LOGGED_IN,
|
SpecialGroup.LOGGED_IN,
|
||||||
);
|
);
|
||||||
expect(await newNote.tags).toHaveLength(0);
|
|
||||||
expect(await newNote.owner).toBeNull();
|
expect(await newNote.owner).toBeNull();
|
||||||
expect(await newNote.aliases).toHaveLength(0);
|
expect(await newNote.aliases).toHaveLength(0);
|
||||||
});
|
});
|
||||||
it('without alias, with owner', async () => {
|
it('without alias, with owner', async () => {
|
||||||
const newNote = await service.createNote(content, user);
|
const newNote = await service.createNote(content, user);
|
||||||
const revisions = await newNote.revisions;
|
expect(createRevisionSpy).toHaveBeenCalledWith(newNote, content);
|
||||||
expect(revisions).toHaveLength(1);
|
expect(await newNote.revisions).toStrictEqual([newRevision]);
|
||||||
expect(revisions[0].content).toEqual(content);
|
|
||||||
expect(await newNote.historyEntries).toHaveLength(1);
|
expect(await newNote.historyEntries).toHaveLength(1);
|
||||||
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
||||||
expect(await newNote.userPermissions).toHaveLength(0);
|
expect(await newNote.userPermissions).toHaveLength(0);
|
||||||
|
@ -409,15 +405,13 @@ describe('NotesService', () => {
|
||||||
expect((await groupPermissions[1].group).name).toEqual(
|
expect((await groupPermissions[1].group).name).toEqual(
|
||||||
SpecialGroup.LOGGED_IN,
|
SpecialGroup.LOGGED_IN,
|
||||||
);
|
);
|
||||||
expect(await newNote.tags).toHaveLength(0);
|
|
||||||
expect(await newNote.owner).toEqual(user);
|
expect(await newNote.owner).toEqual(user);
|
||||||
expect(await newNote.aliases).toHaveLength(0);
|
expect(await newNote.aliases).toHaveLength(0);
|
||||||
});
|
});
|
||||||
it('with alias, without owner', async () => {
|
it('with alias, without owner', async () => {
|
||||||
const newNote = await service.createNote(content, null, alias);
|
const newNote = await service.createNote(content, null, alias);
|
||||||
const revisions = await newNote.revisions;
|
expect(createRevisionSpy).toHaveBeenCalledWith(newNote, content);
|
||||||
expect(revisions).toHaveLength(1);
|
expect(await newNote.revisions).toStrictEqual([newRevision]);
|
||||||
expect(revisions[0].content).toEqual(content);
|
|
||||||
expect(await newNote.historyEntries).toHaveLength(0);
|
expect(await newNote.historyEntries).toHaveLength(0);
|
||||||
expect(await newNote.userPermissions).toHaveLength(0);
|
expect(await newNote.userPermissions).toHaveLength(0);
|
||||||
const groupPermissions = await newNote.groupPermissions;
|
const groupPermissions = await newNote.groupPermissions;
|
||||||
|
@ -434,15 +428,14 @@ describe('NotesService', () => {
|
||||||
expect((await groupPermissions[1].group).name).toEqual(
|
expect((await groupPermissions[1].group).name).toEqual(
|
||||||
SpecialGroup.LOGGED_IN,
|
SpecialGroup.LOGGED_IN,
|
||||||
);
|
);
|
||||||
expect(await newNote.tags).toHaveLength(0);
|
|
||||||
expect(await newNote.owner).toBeNull();
|
expect(await newNote.owner).toBeNull();
|
||||||
expect(await newNote.aliases).toHaveLength(1);
|
expect(await newNote.aliases).toHaveLength(1);
|
||||||
});
|
});
|
||||||
it('with alias, with owner', async () => {
|
it('with alias, with owner', async () => {
|
||||||
const newNote = await service.createNote(content, user, alias);
|
const newNote = await service.createNote(content, user, alias);
|
||||||
const revisions = await newNote.revisions;
|
|
||||||
expect(revisions).toHaveLength(1);
|
expect(createRevisionSpy).toHaveBeenCalledWith(newNote, content);
|
||||||
expect(revisions[0].content).toEqual(content);
|
expect(await newNote.revisions).toStrictEqual([newRevision]);
|
||||||
expect(await newNote.historyEntries).toHaveLength(1);
|
expect(await newNote.historyEntries).toHaveLength(1);
|
||||||
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
||||||
expect(await newNote.userPermissions).toHaveLength(0);
|
expect(await newNote.userPermissions).toHaveLength(0);
|
||||||
|
@ -460,7 +453,6 @@ describe('NotesService', () => {
|
||||||
expect((await groupPermissions[1].group).name).toEqual(
|
expect((await groupPermissions[1].group).name).toEqual(
|
||||||
SpecialGroup.LOGGED_IN,
|
SpecialGroup.LOGGED_IN,
|
||||||
);
|
);
|
||||||
expect(await newNote.tags).toHaveLength(0);
|
|
||||||
expect(await newNote.owner).toEqual(user);
|
expect(await newNote.owner).toEqual(user);
|
||||||
expect(await newNote.aliases).toHaveLength(1);
|
expect(await newNote.aliases).toHaveLength(1);
|
||||||
expect((await newNote.aliases)[0].name).toEqual(alias);
|
expect((await newNote.aliases)[0].name).toEqual(alias);
|
||||||
|
@ -470,9 +462,9 @@ describe('NotesService', () => {
|
||||||
it('and content has length maxDocumentLength', async () => {
|
it('and content has length maxDocumentLength', async () => {
|
||||||
const content = 'x'.repeat(noteMockConfig.maxDocumentLength);
|
const content = 'x'.repeat(noteMockConfig.maxDocumentLength);
|
||||||
const newNote = await service.createNote(content, user, alias);
|
const newNote = await service.createNote(content, user, alias);
|
||||||
const revisions = await newNote.revisions;
|
|
||||||
expect(revisions).toHaveLength(1);
|
expect(createRevisionSpy).toHaveBeenCalledWith(newNote, content);
|
||||||
expect(revisions[0].content).toEqual(content);
|
expect(await newNote.revisions).toStrictEqual([newRevision]);
|
||||||
expect(await newNote.historyEntries).toHaveLength(1);
|
expect(await newNote.historyEntries).toHaveLength(1);
|
||||||
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
||||||
expect(await newNote.userPermissions).toHaveLength(0);
|
expect(await newNote.userPermissions).toHaveLength(0);
|
||||||
|
@ -490,7 +482,6 @@ describe('NotesService', () => {
|
||||||
expect((await groupPermissions[1].group).name).toEqual(
|
expect((await groupPermissions[1].group).name).toEqual(
|
||||||
SpecialGroup.LOGGED_IN,
|
SpecialGroup.LOGGED_IN,
|
||||||
);
|
);
|
||||||
expect(await newNote.tags).toHaveLength(0);
|
|
||||||
expect(await newNote.owner).toEqual(user);
|
expect(await newNote.owner).toEqual(user);
|
||||||
expect(await newNote.aliases).toHaveLength(1);
|
expect(await newNote.aliases).toHaveLength(1);
|
||||||
expect((await newNote.aliases)[0].name).toEqual(alias);
|
expect((await newNote.aliases)[0].name).toEqual(alias);
|
||||||
|
@ -505,9 +496,9 @@ describe('NotesService', () => {
|
||||||
it('default permissions', async () => {
|
it('default permissions', async () => {
|
||||||
mockGroupRepo();
|
mockGroupRepo();
|
||||||
const newNote = await service.createNote(content, user, alias);
|
const newNote = await service.createNote(content, user, alias);
|
||||||
const revisions = await newNote.revisions;
|
|
||||||
expect(revisions).toHaveLength(1);
|
expect(createRevisionSpy).toHaveBeenCalledWith(newNote, content);
|
||||||
expect(revisions[0].content).toEqual(content);
|
expect(await newNote.revisions).toStrictEqual([newRevision]);
|
||||||
expect(await newNote.historyEntries).toHaveLength(1);
|
expect(await newNote.historyEntries).toHaveLength(1);
|
||||||
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
expect(await (await newNote.historyEntries)[0].user).toEqual(user);
|
||||||
expect(await newNote.userPermissions).toHaveLength(0);
|
expect(await newNote.userPermissions).toHaveLength(0);
|
||||||
|
@ -519,7 +510,6 @@ describe('NotesService', () => {
|
||||||
expect((await groupPermissions[0].group).name).toEqual(
|
expect((await groupPermissions[0].group).name).toEqual(
|
||||||
SpecialGroup.LOGGED_IN,
|
SpecialGroup.LOGGED_IN,
|
||||||
);
|
);
|
||||||
expect(await newNote.tags).toHaveLength(0);
|
|
||||||
expect(await newNote.owner).toEqual(user);
|
expect(await newNote.owner).toEqual(user);
|
||||||
expect(await newNote.aliases).toHaveLength(1);
|
expect(await newNote.aliases).toHaveLength(1);
|
||||||
expect((await newNote.aliases)[0].name).toEqual(alias);
|
expect((await newNote.aliases)[0].name).toEqual(alias);
|
||||||
|
@ -561,54 +551,25 @@ describe('NotesService', () => {
|
||||||
describe('getNoteContent', () => {
|
describe('getNoteContent', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const content = 'testContent';
|
const content = 'testContent';
|
||||||
jest
|
const revision = Mock.of<Revision>({ content: content });
|
||||||
.spyOn(noteRepo, 'save')
|
const newNote = Mock.of<Note>();
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
mockRevisionService(newNote, revision);
|
||||||
// @ts-ignore
|
const result = await service.getNoteContent(newNote);
|
||||||
.mockImplementation(async (note: Note): Promise<Note> => note);
|
expect(result).toEqual(content);
|
||||||
mockGroupRepo();
|
|
||||||
const newNote = await service.createNote(content, null);
|
|
||||||
const revisions = await newNote.revisions;
|
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(revisions[0]);
|
|
||||||
await service.getNoteContent(newNote).then((result) => {
|
|
||||||
expect(result).toEqual(content);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getNoteByIdOrAlias', () => {
|
describe('getNoteByIdOrAlias', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const user = User.create('hardcoded', 'Testy') as User;
|
const user = User.create('hardcoded', 'Testy') as User;
|
||||||
const note = Note.create(user);
|
const note = Note.create(user) as Note;
|
||||||
const createQueryBuilder = {
|
mockSelectQueryBuilderInRepo(noteRepo, note);
|
||||||
leftJoinAndSelect: () => createQueryBuilder,
|
|
||||||
where: () => createQueryBuilder,
|
|
||||||
orWhere: () => createQueryBuilder,
|
|
||||||
setParameter: () => createQueryBuilder,
|
|
||||||
getOne: () => note,
|
|
||||||
};
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
const foundNote = await service.getNoteByIdOrAlias('noteThatExists');
|
const foundNote = await service.getNoteByIdOrAlias('noteThatExists');
|
||||||
expect(foundNote).toEqual(note);
|
expect(foundNote).toEqual(note);
|
||||||
});
|
});
|
||||||
describe('fails:', () => {
|
describe('fails:', () => {
|
||||||
it('no note found', async () => {
|
it('no note found', async () => {
|
||||||
const createQueryBuilder = {
|
mockSelectQueryBuilderInRepo(noteRepo, null);
|
||||||
leftJoinAndSelect: () => createQueryBuilder,
|
|
||||||
where: () => createQueryBuilder,
|
|
||||||
orWhere: () => createQueryBuilder,
|
|
||||||
setParameter: () => createQueryBuilder,
|
|
||||||
getOne: () => null,
|
|
||||||
};
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'createQueryBuilder')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
.mockImplementation(() => createQueryBuilder);
|
|
||||||
await expect(
|
await expect(
|
||||||
service.getNoteByIdOrAlias('noteThatDoesNoteExist'),
|
service.getNoteByIdOrAlias('noteThatDoesNoteExist'),
|
||||||
).rejects.toThrow(NotInDBError);
|
).rejects.toThrow(NotInDBError);
|
||||||
|
@ -644,81 +605,111 @@ describe('NotesService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('updateNote', () => {
|
describe('updateNote', () => {
|
||||||
it('works', async () => {
|
it('adds a new revision if content is different', async () => {
|
||||||
const [note, ,] = await getMockData();
|
const [note, , , revision] = await getMockData();
|
||||||
const revisionLength = (await note.revisions).length;
|
|
||||||
const updatedNote = await service.updateNote(note, 'newContent');
|
|
||||||
expect(await updatedNote.revisions).toHaveLength(revisionLength + 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toTagList', () => {
|
const mockRevision = Mock.of<Revision>({});
|
||||||
it('works', async () => {
|
const createRevisionSpy = jest
|
||||||
const note = {} as Note;
|
.spyOn(revisionsService, 'createRevision')
|
||||||
note.tags = Promise.resolve([
|
.mockReturnValue(Promise.resolve(mockRevision));
|
||||||
{
|
|
||||||
id: 1,
|
const newContent = 'newContent';
|
||||||
name: 'testTag',
|
const updatedNote = await service.updateNote(note, newContent);
|
||||||
notes: Promise.resolve([note]),
|
expect(await updatedNote.revisions).toStrictEqual([
|
||||||
},
|
revision,
|
||||||
|
mockRevision,
|
||||||
]);
|
]);
|
||||||
const tagList = await service.toTagList(note);
|
expect(createRevisionSpy).toHaveBeenCalledWith(note, newContent);
|
||||||
expect(tagList).toHaveLength(1);
|
});
|
||||||
expect(tagList[0]).toEqual((await note.tags)[0].name);
|
|
||||||
|
it("won't create a new revision if content is same", async () => {
|
||||||
|
const [note, , , revision] = await getMockData();
|
||||||
|
const createRevisionSpy = jest
|
||||||
|
.spyOn(revisionsService, 'createRevision')
|
||||||
|
.mockReturnValue(Promise.resolve(undefined));
|
||||||
|
|
||||||
|
const newContent = 'newContent';
|
||||||
|
const updatedNote = await service.updateNote(note, newContent);
|
||||||
|
expect(await updatedNote.revisions).toStrictEqual([revision]);
|
||||||
|
expect(createRevisionSpy).toHaveBeenCalledWith(note, newContent);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toNotePermissionsDto', () => {
|
describe('toNotePermissionsDto', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const [note, user, group] = await getMockData();
|
const [note] = await getMockData();
|
||||||
const permissions = await service.toNotePermissionsDto(note);
|
const permissions = await service.toNotePermissionsDto(note);
|
||||||
expect(permissions.owner).toEqual(user.username);
|
expect(permissions).toMatchInlineSnapshot(`
|
||||||
expect(permissions.sharedToUsers).toHaveLength(1);
|
{
|
||||||
expect(permissions.sharedToUsers[0].username).toEqual(user.username);
|
"owner": "hardcoded",
|
||||||
expect(permissions.sharedToUsers[0].canEdit).toEqual(true);
|
"sharedToGroups": [
|
||||||
expect(permissions.sharedToGroups).toHaveLength(1);
|
{
|
||||||
expect(permissions.sharedToGroups[0].groupName).toEqual(
|
"canEdit": true,
|
||||||
group.displayName,
|
"groupName": "testGroup",
|
||||||
);
|
},
|
||||||
expect(permissions.sharedToGroups[0].canEdit).toEqual(true);
|
],
|
||||||
|
"sharedToUsers": [
|
||||||
|
{
|
||||||
|
"canEdit": true,
|
||||||
|
"username": "hardcoded",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toNoteMetadataDto', () => {
|
describe('toNoteMetadataDto', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const [note, user, group] = await getMockData();
|
const [note] = await getMockData();
|
||||||
note.aliases = Promise.resolve([
|
note.aliases = Promise.resolve([
|
||||||
Alias.create('testAlias', note, true) as Alias,
|
Alias.create('testAlias', note, true) as Alias,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const metadataDto = await service.toNoteMetadataDto(note);
|
const metadataDto = await service.toNoteMetadataDto(note);
|
||||||
expect(metadataDto.id).toEqual(note.publicId);
|
expect(metadataDto).toMatchInlineSnapshot(`
|
||||||
expect(metadataDto.aliases).toHaveLength(1);
|
{
|
||||||
expect(metadataDto.aliases[0].name).toEqual((await note.aliases)[0].name);
|
"aliases": [
|
||||||
expect(metadataDto.primaryAddress).toEqual('testAlias');
|
{
|
||||||
expect(metadataDto.title).toEqual(note.title);
|
"name": "testAlias",
|
||||||
expect(metadataDto.description).toEqual(note.description);
|
"noteId": "testId",
|
||||||
expect(metadataDto.editedBy).toHaveLength(1);
|
"primaryAlias": true,
|
||||||
expect(metadataDto.editedBy[0]).toEqual(user.username);
|
},
|
||||||
expect(metadataDto.permissions.owner).toEqual(user.username);
|
],
|
||||||
expect(metadataDto.permissions.sharedToUsers).toHaveLength(1);
|
"createdAt": undefined,
|
||||||
expect(metadataDto.permissions.sharedToUsers[0].username).toEqual(
|
"description": "mockDescription",
|
||||||
user.username,
|
"editedBy": [
|
||||||
);
|
"hardcoded",
|
||||||
expect(metadataDto.permissions.sharedToUsers[0].canEdit).toEqual(true);
|
],
|
||||||
expect(metadataDto.permissions.sharedToGroups).toHaveLength(1);
|
"id": "testId",
|
||||||
expect(metadataDto.permissions.sharedToGroups[0].groupName).toEqual(
|
"permissions": {
|
||||||
group.displayName,
|
"owner": "hardcoded",
|
||||||
);
|
"sharedToGroups": [
|
||||||
expect(metadataDto.permissions.sharedToGroups[0].canEdit).toEqual(true);
|
{
|
||||||
expect(metadataDto.tags).toHaveLength(1);
|
"canEdit": true,
|
||||||
expect(metadataDto.tags[0]).toEqual((await note.tags)[0].name);
|
"groupName": "testGroup",
|
||||||
expect(metadataDto.updatedAt).toEqual(
|
},
|
||||||
(await note.revisions)[0].createdAt,
|
],
|
||||||
);
|
"sharedToUsers": [
|
||||||
expect(metadataDto.updateUsername).toEqual(user.username);
|
{
|
||||||
expect(metadataDto.viewCount).toEqual(note.viewCount);
|
"canEdit": true,
|
||||||
|
"username": "hardcoded",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"primaryAddress": "testAlias",
|
||||||
|
"tags": [
|
||||||
|
"tag1",
|
||||||
|
],
|
||||||
|
"title": "mockTitle",
|
||||||
|
"updateUsername": "hardcoded",
|
||||||
|
"updatedAt": 2019-02-04T20:34:12.000Z,
|
||||||
|
"version": undefined,
|
||||||
|
"viewCount": 1337,
|
||||||
|
}
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns publicId if no alias exists', async () => {
|
it('returns publicId if no alias exists', async () => {
|
||||||
const [note, ,] = await getMockData();
|
const [note, ,] = await getMockData();
|
||||||
const metadataDto = await service.toNoteMetadataDto(note);
|
const metadataDto = await service.toNoteMetadataDto(note);
|
||||||
|
@ -728,41 +719,57 @@ describe('NotesService', () => {
|
||||||
|
|
||||||
describe('toNoteDto', () => {
|
describe('toNoteDto', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const [note, user, group] = await getMockData();
|
const [note] = await getMockData();
|
||||||
note.aliases = Promise.resolve([
|
note.aliases = Promise.resolve([
|
||||||
Alias.create('testAlias', note, true) as Alias,
|
Alias.create('testAlias', note, true) as Alias,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const noteDto = await service.toNoteDto(note);
|
const noteDto = await service.toNoteDto(note);
|
||||||
expect(noteDto.metadata.id).toEqual(note.publicId);
|
expect(noteDto).toMatchInlineSnapshot(`
|
||||||
expect(noteDto.metadata.aliases).toHaveLength(1);
|
{
|
||||||
expect(noteDto.metadata.aliases[0].name).toEqual(
|
"content": "mockContent",
|
||||||
(await note.aliases)[0].name,
|
"editedByAtPosition": [],
|
||||||
);
|
"metadata": {
|
||||||
expect(noteDto.metadata.title).toEqual(note.title);
|
"aliases": [
|
||||||
expect(noteDto.metadata.description).toEqual(note.description);
|
{
|
||||||
expect(noteDto.metadata.editedBy).toHaveLength(1);
|
"name": "testAlias",
|
||||||
expect(noteDto.metadata.editedBy[0]).toEqual(user.username);
|
"noteId": "testId",
|
||||||
expect(noteDto.metadata.permissions.owner).toEqual(user.username);
|
"primaryAlias": true,
|
||||||
expect(noteDto.metadata.permissions.sharedToUsers).toHaveLength(1);
|
},
|
||||||
expect(noteDto.metadata.permissions.sharedToUsers[0].username).toEqual(
|
],
|
||||||
user.username,
|
"createdAt": undefined,
|
||||||
);
|
"description": "mockDescription",
|
||||||
expect(noteDto.metadata.permissions.sharedToUsers[0].canEdit).toEqual(
|
"editedBy": [
|
||||||
true,
|
"hardcoded",
|
||||||
);
|
],
|
||||||
expect(noteDto.metadata.permissions.sharedToGroups).toHaveLength(1);
|
"id": "testId",
|
||||||
expect(noteDto.metadata.permissions.sharedToGroups[0].groupName).toEqual(
|
"permissions": {
|
||||||
group.displayName,
|
"owner": "hardcoded",
|
||||||
);
|
"sharedToGroups": [
|
||||||
expect(noteDto.metadata.permissions.sharedToGroups[0].canEdit).toEqual(
|
{
|
||||||
true,
|
"canEdit": true,
|
||||||
);
|
"groupName": "testGroup",
|
||||||
expect(noteDto.metadata.tags).toHaveLength(1);
|
},
|
||||||
expect(noteDto.metadata.tags[0]).toEqual((await note.tags)[0].name);
|
],
|
||||||
expect(noteDto.metadata.updateUsername).toEqual(user.username);
|
"sharedToUsers": [
|
||||||
expect(noteDto.metadata.viewCount).toEqual(note.viewCount);
|
{
|
||||||
expect(noteDto.content).toEqual('testContent');
|
"canEdit": true,
|
||||||
|
"username": "hardcoded",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"primaryAddress": "testAlias",
|
||||||
|
"tags": [
|
||||||
|
"tag1",
|
||||||
|
],
|
||||||
|
"title": "mockTitle",
|
||||||
|
"updateUsername": "hardcoded",
|
||||||
|
"updatedAt": 2019-02-04T20:34:12.000Z,
|
||||||
|
"version": undefined,
|
||||||
|
"viewCount": 1337,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -104,9 +104,9 @@ describe('RevisionsService', () => {
|
||||||
describe('getRevision', () => {
|
describe('getRevision', () => {
|
||||||
it('returns a revision', async () => {
|
it('returns a revision', async () => {
|
||||||
const note = Mock.of<Note>({});
|
const note = Mock.of<Note>({});
|
||||||
const revision = Revision.create('', '', note) as Revision;
|
const revision = Mock.of<Revision>({});
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(revision);
|
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(revision);
|
||||||
expect(await service.getRevision({} as Note, 1)).toEqual(revision);
|
expect(await service.getRevision(note, 1)).toBe(revision);
|
||||||
});
|
});
|
||||||
it('throws if the revision is not in the databse', async () => {
|
it('throws if the revision is not in the databse', async () => {
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(null);
|
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(null);
|
||||||
|
@ -117,54 +117,55 @@ describe('RevisionsService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('purgeRevisions', () => {
|
describe('purgeRevisions', () => {
|
||||||
|
let revisions: Revision[];
|
||||||
|
let note: Note;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
note = Mock.of<Note>({});
|
||||||
|
revisions = [];
|
||||||
|
|
||||||
|
jest
|
||||||
|
.spyOn(revisionRepo, 'remove')
|
||||||
|
.mockImplementation(
|
||||||
|
<T extends Revision | Revision[]>(deleteEntities: T): Promise<T> => {
|
||||||
|
const newRevisions = revisions.filter((item: Revision) =>
|
||||||
|
Array.isArray(deleteEntities)
|
||||||
|
? !deleteEntities.includes(item)
|
||||||
|
: deleteEntities !== item,
|
||||||
|
);
|
||||||
|
revisions = newRevisions;
|
||||||
|
note.revisions = Promise.resolve(newRevisions);
|
||||||
|
return Promise.resolve(deleteEntities);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('purges the revision history', async () => {
|
it('purges the revision history', async () => {
|
||||||
const note = {} as Note;
|
const revision1 = Mock.of<Revision>({ id: 1 });
|
||||||
note.id = 4711;
|
const revision2 = Mock.of<Revision>({ id: 2 });
|
||||||
let revisions: Revision[] = [];
|
const revision3 = Mock.of<Revision>({ id: 3 });
|
||||||
const revision1 = Revision.create('a', 'a', note) as Revision;
|
revisions = [revision1, revision2, revision3];
|
||||||
revision1.id = 1;
|
|
||||||
const revision2 = Revision.create('b', 'b', note) as Revision;
|
|
||||||
revision2.id = 2;
|
|
||||||
const revision3 = Revision.create('c', 'c', note) as Revision;
|
|
||||||
revision3.id = 3;
|
|
||||||
revisions.push(revision1, revision2, revision3);
|
|
||||||
note.revisions = Promise.resolve(revisions);
|
note.revisions = Promise.resolve(revisions);
|
||||||
|
|
||||||
jest.spyOn(revisionRepo, 'find').mockResolvedValueOnce(revisions);
|
jest.spyOn(revisionRepo, 'find').mockResolvedValueOnce(revisions);
|
||||||
jest.spyOn(service, 'getLatestRevision').mockResolvedValueOnce(revision3);
|
jest.spyOn(service, 'getLatestRevision').mockResolvedValueOnce(revision3);
|
||||||
revisionRepo.remove = jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementation((deleteList: Revision[]) => {
|
|
||||||
revisions = revisions.filter(
|
|
||||||
(item: Revision) => !deleteList.includes(item),
|
|
||||||
);
|
|
||||||
return Promise.resolve(deleteList);
|
|
||||||
});
|
|
||||||
|
|
||||||
// expected to return all the purged revisions
|
// expected to return all the purged revisions
|
||||||
expect(await service.purgeRevisions(note)).toHaveLength(2);
|
expect(await service.purgeRevisions(note)).toStrictEqual([
|
||||||
|
revision1,
|
||||||
|
revision2,
|
||||||
|
]);
|
||||||
|
|
||||||
// expected to have only the latest revision
|
// expected to have only the latest revision
|
||||||
const updatedRevisions: Revision[] = [revision3];
|
expect(revisions).toStrictEqual([revision3]);
|
||||||
expect(revisions).toEqual(updatedRevisions);
|
|
||||||
});
|
});
|
||||||
it('has no effect on revision history when a single revision is present', async () => {
|
it('has no effect on revision history when a single revision is present', async () => {
|
||||||
const note = {} as Note;
|
const revision1 = Mock.of<Revision>({ id: 1 });
|
||||||
note.id = 4711;
|
revisions = [revision1];
|
||||||
let revisions: Revision[] = [];
|
|
||||||
const revision1 = Revision.create('a', 'a', note) as Revision;
|
|
||||||
revision1.id = 1;
|
|
||||||
revisions.push(revision1);
|
|
||||||
note.revisions = Promise.resolve(revisions);
|
note.revisions = Promise.resolve(revisions);
|
||||||
|
|
||||||
jest.spyOn(revisionRepo, 'find').mockResolvedValueOnce(revisions);
|
jest.spyOn(revisionRepo, 'find').mockResolvedValueOnce(revisions);
|
||||||
jest.spyOn(service, 'getLatestRevision').mockResolvedValueOnce(revision1);
|
jest.spyOn(service, 'getLatestRevision').mockResolvedValueOnce(revision1);
|
||||||
revisionRepo.remove = jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementation((deleteList: Revision[]) => {
|
|
||||||
revisions = revisions.filter(
|
|
||||||
(item: Revision) => !deleteList.includes(item),
|
|
||||||
);
|
|
||||||
return Promise.resolve(deleteList);
|
|
||||||
});
|
|
||||||
|
|
||||||
// expected to return all the purged revisions
|
// expected to return all the purged revisions
|
||||||
expect(await service.purgeRevisions(note)).toHaveLength(0);
|
expect(await service.purgeRevisions(note)).toHaveLength(0);
|
||||||
|
@ -188,7 +189,7 @@ describe('RevisionsService', () => {
|
||||||
edits.push(Edit.create(anonAuthor, 29, 20) as Edit);
|
edits.push(Edit.create(anonAuthor, 29, 20) as Edit);
|
||||||
edits.push(Edit.create(anonAuthor, 29, 20) as Edit);
|
edits.push(Edit.create(anonAuthor, 29, 20) as Edit);
|
||||||
edits.push(Edit.create(anonAuthor2, 29, 20) as Edit);
|
edits.push(Edit.create(anonAuthor2, 29, 20) as Edit);
|
||||||
const revision = Revision.create('', '', {} as Note) as Revision;
|
const revision = Mock.of<Revision>({});
|
||||||
revision.edits = Promise.resolve(edits);
|
revision.edits = Promise.resolve(edits);
|
||||||
|
|
||||||
const userInfo = await service.getRevisionUserInfo(revision);
|
const userInfo = await service.getRevisionUserInfo(revision);
|
||||||
|
@ -197,13 +198,122 @@ describe('RevisionsService', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('toRevisionMetadataDto', () => {
|
||||||
|
it('converts a revision', async () => {
|
||||||
|
const revision = Mock.of<Revision>({
|
||||||
|
id: 3246,
|
||||||
|
content: 'mockContent',
|
||||||
|
length: 1854,
|
||||||
|
createdAt: new Date('2020-05-20T09:58:00.000Z'),
|
||||||
|
title: 'mockTitle',
|
||||||
|
tags: Promise.resolve([Mock.of<Tag>({ name: 'mockTag' })]),
|
||||||
|
description: 'mockDescription',
|
||||||
|
patch: 'mockPatch',
|
||||||
|
edits: Promise.resolve([
|
||||||
|
Mock.of<Edit>({
|
||||||
|
endPos: 93,
|
||||||
|
startPos: 34,
|
||||||
|
createdAt: new Date('2020-03-04T20:12:00.000Z'),
|
||||||
|
updatedAt: new Date('2021-12-10T09:45:00.000Z'),
|
||||||
|
author: Promise.resolve(
|
||||||
|
Mock.of<Author>({
|
||||||
|
user: Promise.resolve(
|
||||||
|
Mock.of<User>({
|
||||||
|
username: 'mockusername',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
expect(await service.toRevisionMetadataDto(revision))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"anonymousAuthorCount": 0,
|
||||||
|
"authorUsernames": [
|
||||||
|
"mockusername",
|
||||||
|
],
|
||||||
|
"createdAt": 2020-05-20T09:58:00.000Z,
|
||||||
|
"description": "mockDescription",
|
||||||
|
"id": 3246,
|
||||||
|
"length": 1854,
|
||||||
|
"tags": [
|
||||||
|
"mockTag",
|
||||||
|
],
|
||||||
|
"title": "mockTitle",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('toRevisionDto', () => {
|
||||||
|
it('converts a revision', async () => {
|
||||||
|
const revision = Mock.of<Revision>({
|
||||||
|
id: 3246,
|
||||||
|
content: 'mockContent',
|
||||||
|
length: 1854,
|
||||||
|
createdAt: new Date('2020-05-20T09:58:00.000Z'),
|
||||||
|
title: 'mockTitle',
|
||||||
|
tags: Promise.resolve([Mock.of<Tag>({ name: 'mockTag' })]),
|
||||||
|
description: 'mockDescription',
|
||||||
|
patch: 'mockPatch',
|
||||||
|
edits: Promise.resolve([
|
||||||
|
Mock.of<Edit>({
|
||||||
|
endPos: 93,
|
||||||
|
startPos: 34,
|
||||||
|
createdAt: new Date('2020-03-04T22:32:00.000Z'),
|
||||||
|
updatedAt: new Date('2021-02-10T12:23:00.000Z'),
|
||||||
|
author: Promise.resolve(
|
||||||
|
Mock.of<Author>({
|
||||||
|
user: Promise.resolve(
|
||||||
|
Mock.of<User>({
|
||||||
|
username: 'mockusername',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
expect(await service.toRevisionDto(revision)).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"anonymousAuthorCount": 0,
|
||||||
|
"authorUsernames": [
|
||||||
|
"mockusername",
|
||||||
|
],
|
||||||
|
"content": "mockContent",
|
||||||
|
"createdAt": 2020-05-20T09:58:00.000Z,
|
||||||
|
"description": "mockDescription",
|
||||||
|
"edits": [
|
||||||
|
{
|
||||||
|
"createdAt": 2020-03-04T22:32:00.000Z,
|
||||||
|
"endPos": 93,
|
||||||
|
"startPos": 34,
|
||||||
|
"updatedAt": 2021-02-10T12:23:00.000Z,
|
||||||
|
"username": "mockusername",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"id": 3246,
|
||||||
|
"length": 1854,
|
||||||
|
"patch": "mockPatch",
|
||||||
|
"tags": [
|
||||||
|
"mockTag",
|
||||||
|
],
|
||||||
|
"title": "mockTitle",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('createRevision', () => {
|
describe('createRevision', () => {
|
||||||
it('creates a new revision', async () => {
|
it('creates a new revision', async () => {
|
||||||
const note = Mock.of<Note>({ publicId: 'test-note' });
|
const note = Mock.of<Note>({ publicId: 'test-note', id: 1 });
|
||||||
const oldContent = 'old content\n';
|
const oldContent = 'old content\n';
|
||||||
const newContent = 'new content\n';
|
const newContent =
|
||||||
|
'---\ntitle: new title\ndescription: new description\ntags: [ "tag1" ]\n---\nnew content\n';
|
||||||
|
|
||||||
const oldRevision = Mock.of<Revision>({ content: oldContent });
|
const oldRevision = Mock.of<Revision>({ content: oldContent, id: 1 });
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(oldRevision);
|
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(oldRevision);
|
||||||
jest
|
jest
|
||||||
.spyOn(revisionRepo, 'save')
|
.spyOn(revisionRepo, 'save')
|
||||||
|
@ -214,24 +324,38 @@ describe('RevisionsService', () => {
|
||||||
const createdRevision = await service.createRevision(note, newContent);
|
const createdRevision = await service.createRevision(note, newContent);
|
||||||
expect(createdRevision).not.toBeUndefined();
|
expect(createdRevision).not.toBeUndefined();
|
||||||
expect(createdRevision?.content).toBe(newContent);
|
expect(createdRevision?.content).toBe(newContent);
|
||||||
|
await expect(createdRevision?.tags).resolves.toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
Tag {
|
||||||
|
"name": "tag1",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
expect(createdRevision?.title).toBe('new title');
|
||||||
|
expect(createdRevision?.description).toBe('new description');
|
||||||
await expect(createdRevision?.note).resolves.toBe(note);
|
await expect(createdRevision?.note).resolves.toBe(note);
|
||||||
expect(createdRevision?.patch).toMatchInlineSnapshot(`
|
expect(createdRevision?.patch).toMatchInlineSnapshot(`
|
||||||
"Index: test-note
|
"Index: test-note
|
||||||
===================================================================
|
===================================================================
|
||||||
--- test-note
|
--- test-note
|
||||||
+++ test-note
|
+++ test-note
|
||||||
@@ -1,1 +1,1 @@
|
@@ -1,1 +1,6 @@
|
||||||
-old content
|
-old content
|
||||||
|
+---
|
||||||
|
+title: new title
|
||||||
|
+description: new description
|
||||||
|
+tags: [ "tag1" ]
|
||||||
|
+---
|
||||||
+new content
|
+new content
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("won't create a revision if content is unchanged", async () => {
|
it("won't create a revision if content is unchanged", async () => {
|
||||||
const note = Mock.of<Note>({});
|
const note = Mock.of<Note>({ id: 1 });
|
||||||
const oldContent = 'old content\n';
|
const oldContent = 'old content\n';
|
||||||
|
|
||||||
const oldRevision = Mock.of<Revision>({ content: oldContent });
|
const oldRevision = Mock.of<Revision>({ content: oldContent, id: 1 });
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(oldRevision);
|
jest.spyOn(revisionRepo, 'findOne').mockResolvedValueOnce(oldRevision);
|
||||||
const saveSpy = jest.spyOn(revisionRepo, 'save').mockImplementation();
|
const saveSpy = jest.spyOn(revisionRepo, 'save').mockImplementation();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue