Skip to content

Commit

Permalink
EW-893 adding unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
psachmann committed Jun 11, 2024
1 parent 85998e1 commit 6be9024
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { faker } from '@faker-js/faker';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { IdentityManagementService } from '@infra/identity-management';
import { ObjectId } from '@mikro-orm/mongodb';
Expand Down Expand Up @@ -926,6 +927,7 @@ describe('AccountDbService', () => {
});
});
});

describe('findMany', () => {
describe('when find many one time', () => {
const setup = () => {
Expand Down Expand Up @@ -960,4 +962,43 @@ describe('AccountDbService', () => {
});
});
});

describe('isUniqueEmail', () => {
describe('when email is unique', () => {
const setup = () => {
const email = faker.internet.email();

accountRepo.findByUsername.mockResolvedValue(null);

return { email };
};

it('should return true', async () => {
const { email } = setup();

const result = await accountService.isUniqueEmail(email);

expect(result).toBe(true);
});
});

describe('when email is not unique', () => {
const setup = () => {
const email = faker.internet.email();
const mockTeacherAccount = accountDoFactory.build();

accountRepo.findByUsername.mockResolvedValue(mockTeacherAccount);

return { email, mockTeacherAccount };
};

it('should return false', async () => {
const { email } = setup();

const result = await accountService.isUniqueEmail(email);

expect(result).toBe(false);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ export class AccountServiceDb extends AbstractAccountService {
}

public async isUniqueEmail(email: string): Promise<boolean> {
const foundUsers = await this.userRepo.findByEmail(email);
const isUnique = foundUsers.length === 0;
const account = await this.accountRepo.findByUsername(email);
const isUnique = !account;

return isUnique;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { faker } from '@faker-js/faker';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { MongoMemoryDatabaseModule } from '@infra/database';
import { IdentityManagementOauthService, IdentityManagementService } from '@infra/identity-management';
Expand All @@ -7,8 +8,8 @@ import { Test, TestingModule } from '@nestjs/testing';
import { EntityNotFoundError } from '@shared/common';
import { IdmAccount } from '@shared/domain/interface';
import { Logger } from '@src/core/logger';
import { AccountConfig } from '../../account-config';
import { Account, AccountSave } from '..';
import { AccountConfig } from '../../account-config';
import { AccountIdmToDoMapper, AccountIdmToDoMapperDb } from '../../repo/micro-orm/mapper';
import { AccountServiceIdm } from './account-idm.service';

Expand Down Expand Up @@ -532,4 +533,42 @@ describe('AccountIdmService', () => {
await expect(accountIdmService.findMany(0, 0)).rejects.toThrow(NotImplementedException);
});
});

describe('isUniqueEmail', () => {
describe('when email is unique', () => {
const setup = () => {
const email = faker.internet.email();

idmServiceMock.findAccountsByUsername.mockResolvedValue([[], 0]);

return { email };
};

it('should return true', async () => {
const { email } = setup();

const result = await accountIdmService.isUniqueEmail(email);

expect(result).toBe(true);
});
});

describe('when email is not unique', () => {
const setup = () => {
const email = faker.internet.email();

idmServiceMock.findAccountsByUsername.mockResolvedValue([[mockIdmAccount], 1]);

return { email };
};

it('should return false', async () => {
const { email } = setup();

const result = await accountIdmService.isUniqueEmail(email);

expect(result).toBe(false);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { faker } from '@faker-js/faker';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { MikroORM } from '@mikro-orm/core';
import { ObjectId } from '@mikro-orm/mongodb';
Expand Down Expand Up @@ -28,6 +29,7 @@ import { IdmCallbackLoggableException } from '../error';
import { AccountServiceDb } from './account-db.service';
import { AccountServiceIdm } from './account-idm.service';
import { AccountService } from './account.service';
import { AbstractAccountService } from './account.service.abstract';

describe('AccountService', () => {
let module: TestingModule;
Expand Down Expand Up @@ -2081,4 +2083,24 @@ describe('AccountService', () => {
});
});
});

describe('isUniqueEmail', () => {
describe('when checking if email is unique', () => {
const setup = () => {
const email = faker.internet.email();
const accountImpl = Reflect.get(accountService, 'accountImpl') as DeepMocked<AbstractAccountService>;
const isUniqueEmailSpy = jest.spyOn(accountImpl, 'isUniqueEmail');

return { email, isUniqueEmailSpy };
};

it('should call the underlying account service implementation', async () => {
const { email, isUniqueEmailSpy } = setup();

await accountService.isUniqueEmail(email);

expect(isUniqueEmailSpy).toHaveBeenCalledWith(email);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { EntityManager, ObjectId } from '@mikro-orm/mongodb';
import { Test, TestingModule } from '@nestjs/testing';
import { User } from '@shared/domain/entity';
import { cleanupCollections, userFactory } from '@shared/testing';
import { AccountRepo } from './account.repo';
import { AccountEntity } from '../../domain/entity/account.entity';
import { AccountDoToEntityMapper } from './mapper/account-do-to-entity.mapper';
import { AccountEntityToDoMapper } from './mapper';
import { accountDoFactory, accountFactory } from '../../testing';
import { AccountRepo } from './account.repo';
import { AccountEntityToDoMapper } from './mapper';
import { AccountDoToEntityMapper } from './mapper/account-do-to-entity.mapper';

describe('account repo', () => {
let module: TestingModule;
Expand Down Expand Up @@ -115,6 +115,35 @@ describe('account repo', () => {
});
});

describe('findByUsername', () => {
describe('When username is given', () => {
const setup = async () => {
const accountToFind = accountFactory.build();

await em.persistAndFlush(accountToFind);
em.clear();

return accountToFind;
};

it('should find user by username', async () => {
const accountToFind = await setup();

const account = await repo.findByUsername(accountToFind.username);

expect(account?.username).toEqual(accountToFind.username);
});
});

describe('When username is not given', () => {
it('should return null', async () => {
const account = await repo.findByUsername('');

expect(account).toBeNull();
});
});
});

describe('findByUsernameAndSystemId', () => {
describe('When username and systemId are given', () => {
const setup = async () => {
Expand Down
14 changes: 12 additions & 2 deletions apps/server/src/modules/account/repo/micro-orm/account.repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { EntityManager, ObjectId } from '@mikro-orm/mongodb';
import { Injectable } from '@nestjs/common';
import { SortOrder } from '@shared/domain/interface';
import { Counted, EntityId } from '@shared/domain/types';
import { AccountEntity } from '../../domain/entity/account.entity';
import { AccountDoToEntityMapper } from './mapper/account-do-to-entity.mapper';
import { Account } from '../../domain/account';
import { AccountEntity } from '../../domain/entity/account.entity';
import { AccountEntityToDoMapper } from './mapper';
import { AccountDoToEntityMapper } from './mapper/account-do-to-entity.mapper';
import { AccountScope } from './scope/account-scope';

@Injectable()
Expand Down Expand Up @@ -66,6 +66,16 @@ export class AccountRepo {
return AccountEntityToDoMapper.mapToDo(entity);
}

public async findByUsername(username: string): Promise<Account | null> {
const entity = await this.em.findOne(AccountEntity, { username });

if (!entity) {
return null;
}

return AccountEntityToDoMapper.mapToDo(entity);
}

public async findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise<Account | null> {
const entity = await this.em.findOne(AccountEntity, { username, systemId: new ObjectId(systemId) });

Expand Down
6 changes: 2 additions & 4 deletions src/services/user/hooks/userService.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,9 @@ const checkUniqueEmail = async (hook) => {
return Promise.resolve(hook);
}

// get userId of user entry to edit
const editUserId = hook.id ? hook.id.toString() : undefined;
const unique = await hook.app.service('nest-account-service').isUniqueEmail(email, editUserId);
const isUnique = await hook.app.service('nest-account-service').isUniqueEmail(email);

if (unique) {
if (isUnique) {
return hook;
}
throw new BadRequest(`Die E-Mail Adresse ist bereits in Verwendung!`);
Expand Down
28 changes: 15 additions & 13 deletions test/services/user/hooks/userService.hooks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,18 @@ describe('generateRegistrationLink', () => {

const expectedErrorMessage = 'Roles must be exactly of length one if generateRegistrationLink=true is set.';

const getAppMock = (registrationlinkMock) => ({
service: (service) => {
if (service === '/registrationlink') {
return {
create: async (data) => registrationlinkMock(data),
};
}
throw new Error('unknown service');
},
});
const getAppMock = (registrationlinkMock) => {
return {
service: (service) => {
if (service === '/registrationlink') {
return {
create: async (data) => registrationlinkMock(data),
};
}
throw new Error('unknown service');
},
};
};

it('throws an error if roles is not defined', async () => {
const context = {
Expand Down Expand Up @@ -439,7 +441,6 @@ describe('checkUniqueEmail', () => {

const currentTs = Date.now();
const currentEmail = `current.${currentTs}@account.de`;
const updatedEmail = `Current.${currentTs}@Account.DE`;
const changedEmail = `Changed.${currentTs}@Account.DE`;
const mockUser = {
firstName: 'Test',
Expand All @@ -450,13 +451,14 @@ describe('checkUniqueEmail', () => {
it('fails because of duplicate email', async () => {
const expectedErrorMessage = `Die E-Mail Adresse ist bereits in Verwendung!`;

await testObjects.createTestUser({ email: currentEmail });
const user = await testObjects.createTestUser();
await app.service('nest-account-service').save({ username: user.email, password: 'password', userId: user._id });

const context = {
app,
data: {
...mockUser,
email: updatedEmail,
email: user.email,
},
};

Expand Down

0 comments on commit 6be9024

Please sign in to comment.