Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tnramalho feature/improve test coverage #153

Merged
merged 3 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/nestjs-auth-jwt/src/auth-jwt.module-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ function definitionTransform(
definition: DynamicModule,
extras: AuthJwtOptionsExtrasInterface,
): DynamicModule {
const { providers = [] } = definition;
const { global = false } = extras;
const { providers } = definition;
const { global } = extras;

return {
...definition,
Expand Down
24 changes: 24 additions & 0 deletions packages/nestjs-auth-jwt/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
AuthJwtModule,
AuthJwtStrategy,
AuthJwtGuard,
JwtAuthGuard,
} from './index';

describe('Index', () => {
it('AuthJwtModule should be imported', () => {
expect(AuthJwtModule).toBeInstanceOf(Function);
});

it('AuthJwtStrategy should be imported', () => {
expect(AuthJwtStrategy).toBeInstanceOf(Function);
});

it('AuthJwtGuard should be imported', () => {
expect(AuthJwtGuard).toBeInstanceOf(Function);
});

it('JwtAuthGuard should be imported', () => {
expect(JwtAuthGuard).toBeInstanceOf(Function);
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { ReferenceIdInterface } from '@concepta/ts-core';
import { AuthLocalCredentialsInterface } from '../../interfaces/auth-local-credentials.interface';

export class UserFixture
implements ReferenceIdInterface, AuthLocalCredentialsInterface
{
id!: string;

username!: string;

active!: boolean;

password!: string;

passwordHash!: string | null;

passwordSalt!: string | null;
}
235 changes: 235 additions & 0 deletions packages/nestjs-auth-local/src/auth-local.module-definition.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
import { IssueTokenService } from '@concepta/nestjs-authentication';
import { PasswordValidationService } from '@concepta/nestjs-password';
import { FactoryProvider } from '@nestjs/common';
import { mock } from 'jest-mock-extended';
import { UserLookupServiceFixture } from './__fixtures__/user/user-lookup.service.fixture';
import {
AUTH_LOCAL_MODULE_ISSUE_TOKEN_SERVICE_TOKEN,
AUTH_LOCAL_MODULE_PASSWORD_VALIDATION_SERVICE_TOKEN,
AUTH_LOCAL_MODULE_SETTINGS_TOKEN,
AUTH_LOCAL_MODULE_USER_LOOKUP_SERVICE_TOKEN,
AUTH_LOCAL_MODULE_VALIDATE_USER_SERVICE_TOKEN,
} from './auth-local.constants';
import { AuthLocalController } from './auth-local.controller';
import {
createAuthLocalControllers,
createAuthLocalExports,
createAuthLocalIssueTokenServiceProvider,
createAuthLocalPasswordValidationServiceProvider,
createAuthLocalUserLookupServiceProvider,
createAuthLocalValidateUserServiceProvider,
} from './auth-local.module-definition';
import { AuthLocalValidateUserService } from './services/auth-local-validate-user.service';
import { JwtIssueService } from '@concepta/nestjs-jwt';

describe('Auth-local.module-definition', () => {
describe(createAuthLocalExports.name, () => {
it('should return an array with the expected tokens', () => {
const result = createAuthLocalExports();
expect(result).toEqual([
AUTH_LOCAL_MODULE_SETTINGS_TOKEN,
AUTH_LOCAL_MODULE_USER_LOOKUP_SERVICE_TOKEN,
AUTH_LOCAL_MODULE_ISSUE_TOKEN_SERVICE_TOKEN,
AUTH_LOCAL_MODULE_VALIDATE_USER_SERVICE_TOKEN,
AUTH_LOCAL_MODULE_PASSWORD_VALIDATION_SERVICE_TOKEN,
]);
});
});

describe(createAuthLocalControllers.name, () => {
it('should return a default AuthLocalController', () => {
const result = createAuthLocalControllers();
expect(result).toEqual([AuthLocalController]);
});

it('should return a default AuthLocalController', () => {
const result = createAuthLocalControllers({});
expect(result).toEqual([AuthLocalController]);
});

it('should return a default AuthLocalController', () => {
const result = createAuthLocalControllers({ controllers: undefined });
expect(result).toEqual([AuthLocalController]);
});

it('should return the provided controllers', () => {
const customController = class CustomController {};
const result = createAuthLocalControllers({
controllers: [customController],
});
expect(result).toEqual([customController]);
});

it('should return an empty array if the controllers option is an empty array', () => {
const result = createAuthLocalControllers({ controllers: [] });
expect(result).toEqual([]);
});

it('should return an array with AuthLocalController if the controllers option includes AuthLocalController', () => {
const result = createAuthLocalControllers({
controllers: [AuthLocalController],
});
expect(result).toEqual([AuthLocalController]);
});

it('should return an array with AuthLocalController and the provided controllers if the controllers option includes AuthLocalController and other controllers', () => {
const customController = class CustomController {};
const result = createAuthLocalControllers({
controllers: [AuthLocalController, customController],
});
expect(result).toEqual([AuthLocalController, customController]);
});
});

describe(createAuthLocalValidateUserServiceProvider.name, () => {
class TestUserLookupService extends UserLookupServiceFixture {}
class TestPasswordValidationService extends PasswordValidationService {}
class TestAuthLocalValidateUserService extends AuthLocalValidateUserService {}

const testUserLookupService = mock<TestUserLookupService>();
const testPasswordValidationService = mock<TestPasswordValidationService>();
const testAuthLocalValidateUserService =
new TestAuthLocalValidateUserService(
testUserLookupService,
testPasswordValidationService,
);

it('should return a default validateUserService', async () => {
const provider =
createAuthLocalValidateUserServiceProvider() as FactoryProvider;

const useFactoryResult = await provider.useFactory({});

expect(useFactoryResult).toBeInstanceOf(AuthLocalValidateUserService);
});

it('should return a validateUserService from initialization', async () => {
const provider =
createAuthLocalValidateUserServiceProvider() as FactoryProvider;

const useFactoryResult = await provider.useFactory({
validateUserService: testAuthLocalValidateUserService,
});

expect(useFactoryResult).toBeInstanceOf(TestAuthLocalValidateUserService);
});

it('should return a override validateUserService', async () => {
const provider = createAuthLocalValidateUserServiceProvider({
validateUserService: testAuthLocalValidateUserService,
}) as FactoryProvider;

const useFactoryResult = await provider.useFactory({});

expect(useFactoryResult).toBeInstanceOf(TestAuthLocalValidateUserService);
});
});

describe(createAuthLocalIssueTokenServiceProvider.name, () => {
class TestIssueTokenService extends IssueTokenService {}

const jwtIssuer = mock<JwtIssueService>();
const testIssueTokenService = new TestIssueTokenService(jwtIssuer);

it('should return an issueTokenService', async () => {
const provider =
createAuthLocalIssueTokenServiceProvider() as FactoryProvider;

const useFactoryResult = await provider.useFactory(
{},
testIssueTokenService,
);

expect(useFactoryResult).toBeInstanceOf(TestIssueTokenService);
});

it('should return an issueTokenService from initialization', async () => {
const provider =
createAuthLocalIssueTokenServiceProvider() as FactoryProvider;

const useFactoryResult = await provider.useFactory({
issueTokenService: testIssueTokenService,
});

expect(useFactoryResult).toBeInstanceOf(TestIssueTokenService);
});

it('should return an overridden issueTokenService', async () => {
const provider = createAuthLocalIssueTokenServiceProvider({
issueTokenService: testIssueTokenService,
}) as FactoryProvider;

const useFactoryResult = await provider.useFactory({});

expect(useFactoryResult).toBeInstanceOf(TestIssueTokenService);
});
});

describe(createAuthLocalUserLookupServiceProvider.name, () => {
class LookupService extends UserLookupServiceFixture {}
class OverrideLookupService extends UserLookupServiceFixture {}

it('should return a default userLookupService', async () => {
const provider: FactoryProvider =
createAuthLocalUserLookupServiceProvider({
userLookupService: new OverrideLookupService(),
}) as FactoryProvider;

// useFactory is for when class was initially defined
const useFactoryResult = await provider.useFactory({
userLookupService: new LookupService(),
});
expect(useFactoryResult).toBeInstanceOf(OverrideLookupService);
});

it('should return a userLookupService from initialization', async () => {
const provider: FactoryProvider =
createAuthLocalUserLookupServiceProvider() as FactoryProvider;

// useFactory is for when class was initially defined
const useFactoryResult = await provider.useFactory({
userLookupService: new LookupService(),
});
expect(useFactoryResult).toBeInstanceOf(LookupService);
});
});

describe(createAuthLocalPasswordValidationServiceProvider.name, () => {
class TestPasswordValidationService extends PasswordValidationService {}

const testPasswordValidationService = new TestPasswordValidationService();

it('should return an issueTokenService', async () => {
const provider =
createAuthLocalPasswordValidationServiceProvider() as FactoryProvider;

const useFactoryResult = await provider.useFactory(
{},
testPasswordValidationService,
);

expect(useFactoryResult).toBeInstanceOf(TestPasswordValidationService);
});

it('should return an issueTokenService from initialization', async () => {
const provider =
createAuthLocalPasswordValidationServiceProvider() as FactoryProvider;

const useFactoryResult = await provider.useFactory({
passwordValidationService: testPasswordValidationService,
});

expect(useFactoryResult).toBeInstanceOf(TestPasswordValidationService);
});

it('should return an overridden issueTokenService', async () => {
const provider = createAuthLocalPasswordValidationServiceProvider({
passwordValidationService: testPasswordValidationService,
}) as FactoryProvider;

const useFactoryResult = await provider.useFactory({});

expect(useFactoryResult).toBeInstanceOf(TestPasswordValidationService);
});
});
});
20 changes: 10 additions & 10 deletions packages/nestjs-auth-local/src/auth-local.module-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ function definitionTransform(
definition: DynamicModule,
extras: AuthLocalOptionsExtrasInterface,
): DynamicModule {
const { providers = [] } = definition;
const { controllers, global = false } = extras;
const { providers } = definition;
const { controllers, global } = extras;

return {
...definition,
Expand Down Expand Up @@ -104,7 +104,7 @@ export function createAuthLocalProviders(options: {
}

export function createAuthLocalControllers(
overrides: Pick<AuthLocalOptions, 'controllers'> = {},
overrides?: Pick<AuthLocalOptions, 'controllers'>,
): DynamicModule['controllers'] {
return overrides?.controllers !== undefined
? overrides.controllers
Expand All @@ -126,7 +126,7 @@ export function createAuthLocalOptionsProvider(
}

export function createAuthLocalValidateUserServiceProvider(
optionsOverrides?: AuthLocalOptions,
optionsOverrides?: Pick<AuthLocalOptions, 'validateUserService'>,
): Provider {
return {
provide: AUTH_LOCAL_MODULE_VALIDATE_USER_SERVICE_TOKEN,
Expand All @@ -136,7 +136,7 @@ export function createAuthLocalValidateUserServiceProvider(
AUTH_LOCAL_MODULE_PASSWORD_VALIDATION_SERVICE_TOKEN,
],
useFactory: async (
options: AuthLocalOptionsInterface,
options: Pick<AuthLocalOptions, 'validateUserService'>,
userLookupService: AuthLocalUserLookupServiceInterface,
passwordValidationService: PasswordValidationServiceInterface,
) =>
Expand All @@ -150,13 +150,13 @@ export function createAuthLocalValidateUserServiceProvider(
}

export function createAuthLocalIssueTokenServiceProvider(
optionsOverrides?: AuthLocalOptions,
optionsOverrides?: Pick<AuthLocalOptions, 'issueTokenService'>,
): Provider {
return {
provide: AUTH_LOCAL_MODULE_ISSUE_TOKEN_SERVICE_TOKEN,
inject: [RAW_OPTIONS_TOKEN, IssueTokenService],
useFactory: async (
options: AuthLocalOptionsInterface,
options: Pick<AuthLocalOptions, 'issueTokenService'>,
defaultService: IssueTokenServiceInterface,
) =>
optionsOverrides?.issueTokenService ??
Expand All @@ -166,13 +166,13 @@ export function createAuthLocalIssueTokenServiceProvider(
}

export function createAuthLocalPasswordValidationServiceProvider(
optionsOverrides?: AuthLocalOptions,
optionsOverrides?: Pick<AuthLocalOptions, 'passwordValidationService'>,
): Provider {
return {
provide: AUTH_LOCAL_MODULE_PASSWORD_VALIDATION_SERVICE_TOKEN,
inject: [RAW_OPTIONS_TOKEN, PasswordValidationService],
useFactory: async (
options: AuthLocalOptionsInterface,
options: Pick<AuthLocalOptions, 'passwordValidationService'>,
defaultService: PasswordValidationServiceInterface,
) =>
optionsOverrides?.passwordValidationService ??
Expand All @@ -182,7 +182,7 @@ export function createAuthLocalPasswordValidationServiceProvider(
}

export function createAuthLocalUserLookupServiceProvider(
optionsOverrides?: AuthLocalOptions,
optionsOverrides?: Pick<AuthLocalOptions, 'userLookupService'>,
): Provider {
return {
provide: AUTH_LOCAL_MODULE_USER_LOOKUP_SERVICE_TOKEN,
Expand Down
Loading
Loading